Не открывает файл на SD-карте через библиотеку FatFS по SPI.

ddr2
Offline
Зарегистрирован: 27.12.2020

Есть такая библиотека FatFS для использования SD карт (http://elm-chan.org/fsw/ff/00index_e.html).

В библиотеке есть примеры использования, в которых просят заполнить поля для подстановки своих портов и функций. Что я сделал следующим образом (https://cadlab.io/project/24804/master/files/send_code/mmc_avr_spi.c). 

// mmc_avr_spi.c
#include <avr/io.h>
#include <avr/interrupt.h> 
#include "diskio.h"
#include "mmc_avr.h"

/* AtMega328p 
PB2  --  CS     (Chip Select - Select Slave)
PB3  --  MOSI   (Output from master to slave)
PB4  --  MISO   (Input from slave to master)
PB5  --  SCK    (SPI Bus Master clock Input to slave))
*/
#define  CS     PB2 
#define  MOSI   PB3
#define  MISO   PB4
#define  SCLK   PB5 

/* Peripheral controls (Platform dependent) */
#define CS_LOW()	PORTB &= ~(1 <<CS) /* Set CS (Chip Select = Slave Select (SS)) low */
#define	CS_HIGH()	PORTB |=  (1 <<CS)	/* Set CS high */
#define MMC_CD		1 // Test if card detected. yes:true, no:false, default:true 
#define MMC_WP		0                         // Write Lock enable. (yes true , no false, default: false)

/*--------------------------------------------------------------------------

   Module Private Functions

---------------------------------------------------------------------------*/

/* Definitions for MMC/SDC command */
#define CMD0	(0)			/* GO_IDLE_STATE */
#define CMD1	(1)			/* SEND_OP_COND (MMC) */
#define	ACMD41	(0x80+41)	/* SEND_OP_COND (SDC) */
#define CMD8	(8)			/* SEND_IF_COND */
#define CMD9	(9)			/* SEND_CSD */
#define CMD10	(10)		/* SEND_CID */
#define CMD12	(12)		/* STOP_TRANSMISSION */
#define ACMD13	(0x80+13)	/* SD_STATUS (SDC) */
#define CMD16	(16)		/* SET_BLOCKLEN */
#define CMD17	(17)		/* READ_SINGLE_BLOCK */
#define CMD18	(18)		/* READ_MULTIPLE_BLOCK */
#define CMD23	(23)		/* SET_BLOCK_COUNT (MMC) */
#define	ACMD23	(0x80+23)	/* SET_WR_BLK_ERASE_COUNT (SDC) */
#define CMD24	(24)		/* WRITE_BLOCK */
#define CMD25	(25)		/* WRITE_MULTIPLE_BLOCK */
#define CMD32	(32)		/* ERASE_ER_BLK_START */
#define CMD33	(33)		/* ERASE_ER_BLK_END */
#define CMD38	(38)		/* ERASE */
#define	CMD48	(48)		/* READ_EXTR_SINGLE */
#define	CMD49	(49)		/* WRITE_EXTR_SINGLE */
#define CMD55	(55)		/* APP_CMD */
#define CMD58	(58)		/* READ_OCR */

static volatile DSTATUS Stat = STA_NOINIT;	/* Disk status */

/* 100Hz decrement timers */
static volatile BYTE Timer1;
static volatile UINT Timer2;

static BYTE CardType;			/* Card type flags (b0:MMC, b1:SDv1, b2:SDv2, b3:Block addressing) */

/*-----------------------------------------------------------------------*/
/* Power Control  (Platform dependent)                                   */
/*-----------------------------------------------------------------------*/
/* When the target system does not support socket power control, there   */
/* is nothing to do in these functions and chk_power always returns 1.   */

#define	FCLK_SLOW()	    SPCR |=   (1 << SPR1)|(1 << SPR0);  SPSR &= ~(1 << SPI2X);	/* Set SPI slow clock (100-400kHz) */
#define	FCLK_FAST()	    SPCR &= ~((1 << SPR1)|(1 << SPR0)); SPSR |=  (1 << SPI2X); /* Set SPI fast clock (20MHz max) */

static
void power_on (void)
{
   	/* Configure MOSI/MISO/SCLK/CS pins for SPI */
    DDRB |= (1 << CS);	    // Output -CS 
    DDRB |= (1 << SCLK);	// Output - CLK
    DDRB |= (1 << MOSI);	// Output - MOSI
    DDRB &=~(1 << MISO);	// Input -  MISO

	PORTB |= (1 <<CS);  // set HIGH --  (Chip Select) 

	/* Enable SPI module in SPI mode 0 */
        SPCR = (1 << SPE)|(1 << MSTR); // 1 - enable SPI, Master

	// Wait for 100 ms 
	Timer2 = 10;
	while (Timer2);

	FCLK_SLOW();
}

static
void power_off (void)
{
	/* Disable SPI function */
        SPCR = 0;  

	/* De-configure MOSI/MISO/SCLK/CS pins (set hi-z) */
	DDRB &= ~(1 << CS);		    // Input - CS0
	DDRB &= ~(1 << SCLK);		// Input - CLK
	DDRB &= ~(1 << MOSI);		// Input - MOSI
	DDRB &= ~(1 << MISO);		// Input - MISO
	
	// Disable pull ups on MISO 
	PORTB &= ~(1 << MISO);
}

// mmc_avr_spi.c далее стандартные функции отправки и чтения. 

 

Полный код теста https://cadlab.io/project/24804/master/files/send_code/ Откуда можно скачать все файлы (Dowloads Files). 

main.c -  f_mount() проходит нормально, но при попытке открыть файл "TEST.TXT", который уже есть на карте, тест постоянно выдаёт ошибку (3) - диск не работает. Может кто использовал эту библиотеку? Что не так?

#include <stdio.h>
#include "uart.h"
#include "ff.h"

const char *errors[] = {
	"(0) Succeeded",
	"(1) A hard error occurred in the low level disk I/O layer",
	"(2) Assertion failed",
	"(3) The physical drive cannot work",
	"(4) Could not find the file",
	"(5) Could not find the path",
	"(6) The path name format is invalid",
	"(7) Access denied due to prohibited access or directory full",
	"(8) Access denied due to prohibited access",
	"(9) The file/directory object is invalid",
	"(10) The physical drive is write protected",
	"(11) The logical drive number is invalid",
	"(12) The volume has no work area",
	"(13) There is no valid FAT volume",
	"(14) The f_mkfs() aborted due to any problem",
	"(15) Could not get a grant to access the volume within defined period",
	"(16) The operation is rejected according to the file sharing policy",
	"(17) LFN working buffer could not be allocated",
	"(18) Number of open files > FF_FS_LOCK",
	"(19) Given parameter is invalid"
};

void die (FRESULT rf) {
    printf("error: %d, %s\n", rf, errors[rf]);
    for(;;);
}

int main (void)
{
    FRESULT fr;
    FATFS fs;
    FIL fil;

    uart_init();   

    /* Open or create a log file and ready to append */
    printf("mount: ");
    fr = f_mount(&fs, "", 0);
    if (fr != FR_OK) 
        die(fr);
    puts ("ok.");

    printf("open:");
    fr = f_open (&fil, "TEST.TXT", FA_READ);    /* Open or create a file */ //|FA_WRITE
    if (fr != FR_OK) 
        die(fr);
    puts("ok.");

    for (;;);
    return 0;
}

Где ошибка? 

ddr2
Offline
Зарегистрирован: 27.12.2020

После загрузки этого main.c -  hex'a на Ардуину постоянно горит "L" - светодиод. 

Так же забыл добавить, что в Аrduino SD карта работает, CardInfo, ReadWrite, а светодиод "L" не горит. 

Подключаю карту 

PB2  --  CS     (Chip Select - Select Slave) (Pin 10)
PB3  --  MOSI   (Output from master to slave) (Pin 11)
PB4  --  MISO   (Input from slave to master) (Pin 12)
PB5  --  SCK    (SPI Bus Master clock Input to slave)) (Pin 13)

Vcc -> +5V
GRD
Остальные файлы проекта стандартные, из примера. 
uart.h,.c - для отправки инфы с ардуины.  
 
 
Может у кого есть рабочий пример работы FatFs c Ардуиной ? 
 

 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

GND с GND соединены?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

1. С чем связана необходимость использования именно этой библиотеки?

2. Какой объем имеет SD и как она отформатирована?

 

И еще один вопрос: название библиотеки позволяет предположить, что она предназначена не для SD карт, а для MMC. Вы уверены в том, что применяете библиотеку именно для тех карт, для которых она предназначена?

ddr2
Offline
Зарегистрирован: 27.12.2020

BOOM пишет:
GND с GND соединены?
Да 

andriano пишет:
1. С чем связана необходимость использования именно этой библиотеки? 

Эта библиотека легко собирается, и не требует использования Arduino-Core, как требует Arduino-SD. 

andriano пишет:
2. Какой объем имеет SD и как она отформатирована?
32 ГБ. Fat32

andriano пишет:
название библиотеки позволяет предположить, что она предназначена не для SD карт, а для MMC. Вы уверены в том, что применяете библиотеку именно для тех карт, для которых она предназначена?
Пишут что поддерживает Secure Digital Memory Card (SDC below). 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

ddr2 пишет:

32 ГБ. Fat32

Пишут что поддерживает Secure Digital Memory Card (SDC below). 

Строго говоря, SD - это не больше 2-4 Гб, а 32 Гб - это уже SDHC.

И, кстати, у MMC тоже ограничение 4 Гб. Так что, вполне возможно, библиотека и не должна поддерживать 32 Гб.

Попробуйте, как библиотека работает с картами 2-4 Гб.

ddr2
Offline
Зарегистрирован: 27.12.2020

andriano пишет:
 Попробуйте, как библиотека работает с картами 2-4 Гб.
К сожалению, у меня нет таких карт, все 32 ГБ, но попробую отформатировать в Fat16. В документации пишут что поддерживается Fat12, Fat16, Fat32, exFat. И карты в плоть до SDXC. Но так как библиотека с приставкой "b", то возможно это сырая бета и есть ошибки в низкоуровневых функциях в "примерах", которые не являются универсальными для всех карт.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

ddr2 пишет:

andriano пишет:
2-4 Гб.
К сожалению, у меня нет таких карт

Ну так, раз занимаетесь Ардуино, такие карты надо целенаправленно искать и покупать впрок.

 

Кстати, не так давно нашел у китайцев карты даже на 128 Мбайт. Так что было бы желание.

b707
Offline
Зарегистрирован: 26.05.2017

ddr2 - а в чем смысл отказа от Ардуино коре, если в ардуино, как вы пишете, карта работает?

Вы точно уверены, что ваш уровень достаточен для отказа от ардуиновских библиотек?

b707
Offline
Зарегистрирован: 26.05.2017

ddr2

где-то я уже такое видел: - не у вас ли?

#define  CS     PB2

#define CS_LOW()    PORTB &= ~(1 <<CS)

вы уверены, что нижний макрос работает именно так, как вы ожидаете? проверяли, чему равно PB2 ?

 

Добавка - да, точно, память еще работает :) Именно у вас я это и видел, в ветке про прерывания 2 недели назад. Ошибка та же самая.
Какой смысл задавть вопросы в форуме, если вы ничему не учитесь?

ddr2
Offline
Зарегистрирован: 27.12.2020
andriano пишет:
Ну так, раз занимаетесь Ардуино, такие карты надо целенаправленно искать и покупать впрок. Кстати, не так давно нашел у китайцев карты даже на 128 Мбайт. Так что было бы желание.
Чтож, буду искать карты 128 МБ. 
 
b707 пишет:
ddr2 - а в чем смысл отказа от Ардуино коре, если в ардуино, как вы пишете, карта работает?
Вы точно уверены, что ваш уровень достаточен для отказа от ардуиновских библиотек?
 
У меня были наброски программы на С с Makefile, поэтому приглянулась FatFS так как её просто присоединить к проекту в отличии от Ардуино-кор, с кучей CPP-файлов. 
Теперь наверное придётся переезжать на Arduino-Core, там SD-lib стабильно работает. 
Оценка моего уровня меня не особо заботит.
 
b707 пишет:
#define CS PB2
#define CS_LOW() PORTB &= ~(1 <<CS)

вы уверены, что нижний макрос работает именно так, как вы ожидаете? проверяли, чему равно PB2 

PB2 - равно 2.
При вызове нижний макрос должен занулять пин PB2 порта PORTB ( digitalWrite(PB2, LOW); ). 
 
Да с прерыванием там была беда, установил pinMode(int1, input);  после чего int1 отказывался реагировать изменения. После удаления этой настройки, всё заработало.