Beispiel #1
0
/*
 * This function synchronously waits any pending block transfers
 * are finished. If your program needs to ensure a block has finished
 * transferring, call this function.
 *
 * Note that sd_read_block() and sd_write_block() already call this
 * function internally before attempting a new transfer, so there are
 * only two times when a user would need to use this function.
 *
 * 1) When the processor will be shutting down. All pending
 *    writes should be finished first.
 * 2) When the user needs the result of an sd_read_block() call
 *    right away.
 */
void sd_wait_notbusy(sd_context_t *sdc)
{
	/* Just twiddle our thumbs until the transfer's done */
	while ((DMA0CTL & DMAEN) != 0);

	/* Reset the DMA controller */
	DMACTL0 = 0;

	/* Ignore the checksum */
	sd_delay(4);

	/* Check for the busy flag (set on write block) */
	if (sdc->busyflag == 1) {
		while (spi_recv_byte() != 0xFF);
		sdc->busyflag = 0;
	}

	/* Deassert CS */
	spi_cs_deassert();

	/*
	 * Send some extra clocks so the card can resynchronize
	 * on next transfer
	 */
	sd_delay(2);
}
Beispiel #2
0
//**********************************************************************************//
// Function Name: spi_recv_data					 									//
// Arguments	: U8 *data, U16 no_bytes	     									//
// Return Types	: NONE																//
// Description	: Function to receive no of bytes from slave specified by	        //
//                "U16 no_byte" the argument & are stored in "U8 *data"             //
//**********************************************************************************//
void spi_recv_data(U8 *data, U16 no_byte)
{
    U16 temp_count;
    for(temp_count = 0; temp_count < no_byte; temp_count++)
    {
        *data = spi_recv_byte();
        data++;
    }
}
Beispiel #3
0
/*
 * This function writes a single block to the SD card at block
 * blockaddr. Returns 1 if the command was successful, zero
 * otherwise.
 *
 * This is an ASYNCHRONOUS call. The transfer will not be complete
 * when the function returns. If you want to explicity wait until
 * any pending transfer are finished, use the function
 * sd_wait_notbusy(sdc)
 *
 * sd_context_t *sdc   -- A pointer to an sd device context structure,
 *                        populated by the function sd_initialize()
 * u32 blockaddr       -- The block address to write to the card.
 *                        This is a block address, not a linear address.
 * unsigned char *data -- The data, a pointer to an array of unsigned
 *                        chars.
 */
int sd_write_block(sd_context_t *sdc, u32 blockaddr,
	unsigned char *data)
{

	/* Adjust the block address to a linear address */
	blockaddr <<= SD_BLOCKSIZE_NBITS;

	/* Wait until any old transfers are finished */
	sd_wait_notbusy(sdc);

	/* Pack the address */
	sd_packarg(argument, blockaddr);

	if (sd_send_command(sdc, CMD24, CMD24_R, response, argument) == 0)
		return 0;

	/* Check for an error, like a misaligned write */
	if (response[0] != 0)
		return 0;

	/* Re-assert CS to continue transfer */
	spi_cs_assert();

	/*
	 * The write command need an addition 8 lock cycles before the
	 * block write is started
	 */
	spi_recv_byte();

	/* Clear any pending flags */
	IFG1 &= ~(URXIFG0 | UTXIFG0);

	/* Get the block */
	/* Source DMA address: receive register */
	DMA0SA = (unsigned int)data;
	/* Destination DMA address: the user data buffer */
	DMA0DA = U0TXBUF_;
	/* The size of the block to be transfered */
	DMA0SZ = SD_BLOCKSIZE;
	/* Configure the DMA transfer */
	DMA0CTL =
		DMADT_0 |                  /* Single transfer mode */
		DMASBDB |                  /* Byte mode */
		DMAEN |                    /* Enable DMA */
		DMADSTINCR1 | DMADSTINCR0; /* Increment the destination address */

	/* DMA trigger UART send */
	DMACTL0 = DMA0TSEL_3;

	/* Kick off transfer by sending the first byte */
	U0TXBUF = SD_TOK_WRITE_STARTBLOCK;

	/*
	 * Signal that the card may be busy, so any subsequent commands
	 * should wait for the busy signalling to end (indicated by a
	 * nonzero response)
	 */
	sdc->busyflag = 1;

	return 1;
}
Beispiel #4
0
/*
 * This function reads a single block from the SD card at block
 * blockaddr. The buffer must be preallocated. Returns 1 if the
 * command was successful, zero otherwise.
 *
 * This is an ASYNCHRONOUS call. The transfer will not be complete
 * when the function returns. If you want to explicity wait until
 * any pending transfer are finished, use the function
 * sd_wait_notbusy(sdc)
 *
 * sd_context_t *sdc   -- A pointer to an sd device context structure,
 *                        populated by the function sd_initialize()
 * u32 blockaddr       -- The block address to read from the card.
 *                        This is a block address, not a linear address.
 * unsigned char *data -- The data, a pointer to an array of unsigned
 *                        chars.
 */
int sd_read_block(sd_context_t *sdc, u32 blockaddr,
	unsigned char *data)
{
	u32 i = 0;
	unsigned char tmp;

	/* Adjust the block address to a linear address */
	/* blockaddr <<= SD_BLOCKSIZE_NBITS; */

	/* Wait until any old transfers are finished */
	sd_wait_notbusy(sdc);

	/* Pack the address */
	sd_packarg(argument, blockaddr);

	/* Need to add size checking */
	if (sd_send_command(sdc, CMD17, CMD17_R, response, argument) == 0)
		return 0;

	/* Check for an error, like a misaligned read */
	if (response[0] != 0)
		return 0;

	/* Re-assert CS to continue the transfer */
	spi_cs_assert();

	/* Wait for the token */
	i = 0;
	do {
		tmp = spi_recv_byte();
		i++;
	} while ((tmp == 0xFF) && i < sdc->timeout_read);

	if ((tmp & MSK_TOK_DATAERROR) == 0) {
		/* Clock out a byte before returning */
		spi_send_byte(0xFF);
		/* The card returned an error response. Ball and return 0 */
		return 0;
	}

	IFG1 &= ~URXIFG0;
	IFG1 &= ~UTXIFG0;

	/* Get the block */
	/* Source DMA address: receive register */
	DMA0SA = U0RXBUF_;
	/* Destination DMA address: the user data buffer */
	DMA0DA = (unsigned int)data;
	/* The size of the block to be transfered */
	DMA0SZ = SD_BLOCKSIZE;
	/* Configure the DMA transfer */
	DMA0CTL =
		DMADT_0 |                  /* Single transfer mode */
		DMASBDB |                  /* Byte mode */
		DMAEN |                    /* Enable DMA */
		DMADSTINCR1 | DMADSTINCR0; /* Increment the destination address */

	/*
	 * We depend on the DMA priorities here. Both triggers occur at
	 * the same time, sine the source is identical. DMA0 is handled
	 * first, and retrieves the byte. DMA1 is triggered next, and
	 * sends the next byte.
	 */
	/* Source DMA address: constant 0xFF (don't increment) */
	DMA1SA = (unsigned int)&blank;
	/* Destination DMA address: the transmit buffer */
	DMA1DA = U0TXBUF_;
	/* Increment the destination address */
	/* The size of the block to be transfered */
	DMA0SZ = SD_BLOCKSIZE - 1;
	/* Configure the DMA transfer */
	DMA1CTL =
		DMADT_0 |                  /* Single transfer mode */
		DMASBDB |                  /* Byte mode */
		DMAEN;                     /* Enable DMA */

	/* DMA trigger UART receive for both DMA0 and DMA1 */
	DMACTL0 = DMA0TSEL_3 | DMA1TSEL_3;

	/* Kick off transfer by sending the first byte */
	U0TXBUF = 0xFF;

	return 1;
}