SPI MMC

Go To Last Post
17 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Guys, I'm preparing to write a FAT filing system for a sd card.  However I must first setup the SPI bus.  I've included an example below of the SPI1 (set as master) and SPI2 (set as slave) communicating. Ideally I want to configure the setup to send and receive on either on a single port/SPI bus.  The example uses DMA transfers.

 

#define DMA_TRANS_SIZE 256

/** define the address of SPI master */
#define SPI_MASTER_BUS BUS(BUS_TYPE_SPI, 1)
/** define the CS signal of SPI master */
#define SPI_MASTER_CS 3
/** define the bitrate of SPI master */
#define SPI_MASTER_BITRATE 1000
/** define the pins of SPI master */
#define SPI_MASTER_PINS PINS_SPI1_NPCS3_ALT

/** define the address of SPI slave */
#define SPI_SLAVE_ADDR SPI2
/** define the pins of SPI slave */
#define SPI_SLAVE_PINS PINS_SPI2_NPCS0

/*----------------------------------------------------------------------------
 *        Local variables
 *----------------------------------------------------------------------------*/

/** data buffer for SPI master's receive */
CACHE_ALIGNED static uint8_t spi_buffer_master_tx[DMA_TRANS_SIZE];

/** data buffer for SPI slave's transfer */
CACHE_ALIGNED static uint8_t spi_buffer_slave_rx[DMA_TRANS_SIZE];

/** Pio pins for SPI slave */
static const struct _pin pins_spi_slave[] = SPI_SLAVE_PINS;

/** descriptor for SPI master */
static const struct _bus_dev_cfg spi_master_dev = {
	.bus = SPI_MASTER_BUS,
	.spi_dev = {
		.chip_select = SPI_MASTER_CS,
		.bitrate = SPI_MASTER_BITRATE,
		.delay = {
			.bs = 0,
			.bct = 0,
		},
		.spi_mode = SPID_MODE_0,
	},
};

static struct _spi_desc spi_slave_dev = {
	.addr = SPI_SLAVE_ADDR,
	.chip_select = 0,
	.transfer_mode = BUS_TRANSFER_MODE_DMA,
};

/*----------------------------------------------------------------------------
 *        Local functions
 *----------------------------------------------------------------------------*/

/**
 * \brief Displays the user menu.
 */
static void _display_menu(void)
{
	printf("\r\nMenu :\r\n");
	printf("------\r\n");
	printf("  s: Perform SPI transfer start\r\n");
	printf("  h: Display menu \r\n\r\n");
}

static int _spi_slave_transfer_callback(void* arg, void* arg2)
{
	printf("Slave transfer complete\r\n");
	return 0;
}

/**
 * \brief Start SPI slave transfer and SPI master receive.
 */
static void _spi_transfer(void)
{
	int err;
	int i;
	struct _buffer master_buf = {
		.data = spi_buffer_master_tx,
		.size = DMA_TRANS_SIZE,
		.attr = BUS_BUF_ATTR_TX | BUS_SPI_BUF_ATTR_RELEASE_CS,
	};
	struct _buffer slave_buf = {
		.data = spi_buffer_slave_rx,
		.size = DMA_TRANS_SIZE,
		.attr = BUS_BUF_ATTR_RX,
	};
	struct _callback _cb = {
		.method = _spi_slave_transfer_callback,
		.arg = 0,
	};

	for (i = 0; i < DMA_TRANS_SIZE; i++)
		spi_buffer_master_tx[i] = i;
	memset(spi_buffer_slave_rx, 0, DMA_TRANS_SIZE);

	bus_start_transaction(spi_master_dev.bus);

	printf("Slave receiving...\r\n");
	err = spid_transfer(&spi_slave_dev, &slave_buf, 1, &_cb);
	if (err < 0) {
		trace_error("SPI: SLAVE: transfer failed.\r\n");
		return;
	}

	printf("Master sending...\r\n");
	bus_transfer(spi_master_dev.bus, spi_master_dev.spi_dev.chip_select, &master_buf, 1, NULL);
	bus_stop_transaction(spi_master_dev.bus);
	spid_wait_transfer(&spi_slave_dev);

	if (memcmp(spi_buffer_master_tx, spi_buffer_slave_rx, DMA_TRANS_SIZE)) {
		trace_error("SPI: received data does not match!\r\n");
		return;
	}

	printf("Received data matched.\r\n");
}

/*----------------------------------------------------------------------------
 *        Global functions
 *----------------------------------------------------------------------------*/

/**
 *  \brief SPI slave Application entry point.
 *
 *  \return Unused (ANSI-C compatibility).
 */
int main(void)
{
	uint8_t key;

	/* Output example information */
	console_example_info("SPI Slave Example");

	/* Configure SPI slave */
	pio_configure(pins_spi_slave, ARRAY_SIZE(pins_spi_slave));
	spid_configure(&spi_slave_dev);

	spid_configure_master(&spi_slave_dev, false);
	spid_configure_cs(&spi_slave_dev, 0, 0, 0, 0, SPID_MODE_0);

	// DMA configuration
	bus_configure_slave(spi_master_dev.bus, &spi_master_dev);

	_display_menu();

	while (1) {
		key = console_get_char();
		switch (key) {
		case 'H':
		case 'h':
			_display_menu();
			break;
		case 'S':
		case 's':
			_spi_transfer();
			break;
		default:
			break;
		}
	}
}

Could one of you kind fellas show me how to achieve reading and writing from the same SPI bus?

Last Edited: Tue. Nov 20, 2018 - 04:43 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Could I simply point spi_master_dev at SPI2 to transmit from SPI2??

/** descriptor for SPI master */
static const struct _bus_dev_cfg spi_master_dev = {
	.bus = SPI_MASTER_BUS,
	.spi_dev = {
		.chip_select = SPI_MASTER_CS,
		.bitrate = SPI_MASTER_BITRATE,
		.delay = {
			.bs = 0,
			.bct = 0,
		},
		.spi_mode = SPID_MODE_0,
	},
};

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

To talk to a sdcard, you want to be the spi master. There is no changing of master to slave. With spi you send and receive at the same time. Look at chan’s fat FS.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Okay, I've SPI1 setup has Master and SPI2 setup has Slave.  I'm trying to learn how to configure SPI1 to also receive.  

 

I'm not sure why the spi_slave_dev is configured as Master, see blow

	spid_configure_master(&spi_slave_dev, false);

I'm also not sure why the spi_master_dev is configured as Slave.


	bus_configure_slave(spi_master_dev.bus, &spi_master_dev);

 

Can I change the spi_slave_dev  to receive from SPI1????

 

 

 

 

 

EDITED, I want to create a FAT32 or NTFS (if possible) filing system. 

Last Edited: Sun. Nov 18, 2018 - 09:36 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Does the chip you’re using have a native sdcard interface? This is going to be significantly faster than SPI

Nevertheless, you need to implement sector read/write functions, then the fun comes with the filesystem. You might want to consider a journaling file system for an embedded system.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

yes, the device has hardware sd card interface.  I'll have a look at it tomorrow but I have no examples or data on the interface.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Okie Dokie, I've a MMCSD driver.  I've tried two SD Cards in it but it does not respond to commands sent to it.  I've just read that  MMC and SD Cards are actually different.  Is it possible that the SD cards I have are not working because they're SD and not MMC???

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am actually working on a similar thing, which is writing sensor data to a micro SD card with a SAMG55. I have done this once before with a different manufacturer of MCUs.    SD and MMC are pretty much the same thing, SD just has the "secure" ability and I am sure there are also a few other differences.  I would think SPI would be the easiest way to do this, as the Chan FATFS examples are all for SPI.  With SPI, it is basically an exchange of data when you do a write.  (If you only care about data to read, you just write out "dummy bytes" like 0xFF or 0x00).  If speed isn't a crucial issue for you, I would just use SPI and not SD.  SD can be hard to debug too since you have to me a member of the SD group to have access to the specifications.  But I do have those specs if you go that route and have questions.  I had to design an SDHC controller years ago. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The SAMA5D44 has native interface for MMC/SD so I would like to get it working.  If not I can fall back on SPI which I also have questions about.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Did you turn on power to the interface? There’s a mosfet to do this.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's reporting that the SD card uses 3.0V to 3.3V

The development board is the SAMA5D44 Xplained Ultra

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman, what do you mean there is a mosfet to turn th power on?

 

I had a quick look at the schematic, it lists a power connection "MCI1_PWR_PE4" do I drive that high?????

Last Edited: Tue. Nov 20, 2018 - 04:01 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

in case someone has the same trouble, you have to drive the PE4 pin low to supply power to the MMC card.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I tried driving the PE4 pin low but still not joy.  MAybe I have not configured the pin correctly???  Have a look and see lads.

 

EDITED 1, had a quick search of the example files and found that it should be PIO_OUTPUT_0, still not working!!!

	struct _pin * PIN_MMC;

	PIN_MMC->group = PIO_GROUP_E;
	PIN_MMC->mask = PIO_PE4;
	PIN_MMC->type = PIO_OUTPUT_1;
	PIN_MMC->attribute = PIO_DEFAULT;

	pio_configure(PIN_MMC, 1);
	pio_clear(PIN_MMC);

EDITED 2, The device is reporting the following:

 

-I- Device clk 400 kHz
-E- Cmd52 ERR_NO_RESPONSE
-E- Cmd5 ERR_NO_RESPONSE
-I- Device supports 3.0V:[XXXXXX] 3.3V:[XXXXXX]
-I- SDHC MEM

 

I detects that the cards is inserted therefore there must be power going to it, I read somewhere in the documentation that without power it not report the SD card....

 

Last Edited: Tue. Nov 20, 2018 - 04:46 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Did you leave out some code? If not it looks like you are using a pointer (PIN_MMC) without allocation.

    struct _pin PIN_MMC;

    PIN_MMC.group = PIO_GROUP_E;
    PIN_MMC.mask = PIO_PE4;
    PIN_MMC.type = PIO_OUTPUT_0;
    PIN_MMC.attribute = PIO_DEFAULT;

    pio_configure(&PIN_MMC, 1);
    pio_clear(&PIN_MMC);

would be the fix for that.
/Lars

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

shit!!!  How did I manage to do that?

 

Still no response from said device!!!

Last Edited: Tue. Nov 20, 2018 - 05:14 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Still working on this bug.  I accidentally left it run and realised that after a period of 5 to 10 minutes it displayed the information requested.  See below:

 

SD Card menu:
   h: Display this menu
   t: Toggle between Slot 0 (microSD) and Slot[1](SD/MMC)
   i: Display device info
   l: Mount FAT file system and list files
   r: Read the file named 'test_data.bin'
   w: Perform a basic RAW read/write test.

-I- Device clk 400 kHz
-E- Cmd52 ERR_NO_RESPONSE
-E- Cmd5 ERR_NO_RESPONSE
-I- SDHC MEM
-E- Cmd51 ERR_NO_RESPONSE
-E- Acmd51 ERR_NO_RESPONSE
-E- Cmd13 ERR_NO_RESPONSE
-E- Acmd13 ERR_NO_RESPONSE
-E- Cmd6 ERR_NO_RESPONSE
-E- Cmd51 ERR_NO_RESPONSE
-E- Acmd51 ERR_NO_RESPONSE
-E- Cmd13 ERR_NO_RESPONSE
-E- Acmd13 ERR_NO_RESPONSE
-I- Device clk 25000 kHz
-I- SD/MMC device initialization successful
High-capacity SD card, 4-bit data, in DS mode at 25000 kHz
Device memory size: 30436 MiB, 62333952 * 512B
=== Card IDentification ================
 .MID                        0x03
 .OID                        SD
 .PNM                        SL32G
 .PRV                        8.0
 .PSN                        0xE8532A92
 .MDT                        2017/08
 .CRC                        0x46
=== SD Card Configuration ==============
 .SCR_STRUCT                 0x2
 .SD_SPEC                    0x0
 .SD_SPEC3                   0
 .SD_SPEC4                   0
 .DATA_ST_AFTER_ER           0
 .SD_SEC                     0x0
 .EX_SEC                     0x0
 .SD_BUS_WIDTHS              0x0
 .CMD20                      0
 .CMD23                      0
 .CMD48/49                   0
 .CMD58/59                   0
=== SD Status ==========================
 .DAT_BUS_WIDTH              0x0
 .SEC_MODE                   0
 .SD_CARD_TYPE               0x0200
 .PAREA_SIZE                 16400
 .SPD_CLASS                  0x00
 .UHS_SPD_GRADE              0x3
 .PE_MOVE                    0 MB/sec
 .AU_SIZE                    0x0
 .UHS_AU_SIZE                0x0
 .ER_SIZE                    2560 AU
 .ER_TIMEOUT                 0 sec
 .ER_OFFS                    0 sec
=== Card-Specific Data =================
 .CSD_STRUCT                 0x1
 .TAAC                       0xE
 .NSAC                       0x0
 .TRAN_SPD                   0x32
 .CCC                        0x5B5
 .RD_BL_LEN                  0x9
 .RD_BL_PART                 0
 .WR_BL_MALIGN               0
 .RD_BL_MALIGN               0
 .DSR_IMP                    0
 .C_SIZE                     0xEDC8
 .ER_BL_EN                   1
 .SECT_SIZE                  0x7F
 .WP_GRP_SIZE                0x0
 .WP_GRP_EN                  0
 .R2W_FACT                   0x2
 .WR_BL_LEN                  0x9
 .WR_BL_PART                 0
 .FILE_FMT_GRP               0
 .COPY                       1
 .PERM_WP                    0
 .TMP_WP                     0
 .FILE_FMT                   0x0
 .CRC                        0x61
 

During the following phase:

-E- Cmd52 ERR_NO_RESPONSE
-E- Cmd5 ERR_NO_RESPONSE
-I- SDHC MEM
-E- Cmd51 ERR_NO_RESPONSE
-E- Acmd51 ERR_NO_RESPONSE
-E- Cmd13 ERR_NO_RESPONSE
-E- Acmd13 ERR_NO_RESPONSE
-E- Cmd6 ERR_NO_RESPONSE
-E- Cmd51 ERR_NO_RESPONSE
-E- Acmd51 ERR_NO_RESPONSE
-E- Cmd13 ERR_NO_RESPONSE
-E- Acmd13 ERR_NO_RESPONSE
-I- Device clk 25000 kHz
-I- SD/MMC device initialization successful
 

It takes a long time execute.