OpenCores
URL https://opencores.org/ocsvn/funbase_ip_library/funbase_ip_library/trunk

Subversion Repositories funbase_ip_library

[/] [funbase_ip_library/] [trunk/] [TUT/] [ip.hwp.storage/] [sdram2hibi/] [1.0/] [drv/] [sdram_drv.c] - Rev 147

Go to most recent revision | Compare with Previous | Blame | View Log

// **************************************************************************
// File             : sdram_drv.c
// Authors          : Antti Kojo
// Date             : 12.06.2009
// Decription       : SDRAM contoller driver for eCos
// Version history  : 12.06.2009    ank    Original version
// **************************************************************************
 
#include <cyg/kernel/kapi.h>
#include <cyg/hal/hal_intr.h>
#include <assert.h>
#include "tut_n2h_regs.h"
#include "sdram_drv.h"
#include "N2H_registers_and_macros.h"
#include "types.h"
#include "comm.h"
 
#define SDRAM_CONFIG_SENDBUF_SIZE      (4)
#define SDRAM_READ_CONFIG_WORDS        (4)
#define SDRAM_WRITE_CONFIG_WORDS       (3)
 
/* config word positions */
#define SDRAM_ADDR_CONFIG              (0)
#define DATA_AMOUNT_CONFIG             (1)
#define RCV_HIBI_ADDR_CONFIG           (2)
 
/* This function must be provided by the application.
   Function is called when data has been received. */
extern void sdram_rx_end(uint32* data, uint32 data_length);
 
 
/* Semaphore for SDRAM configuration */
cyg_sem_t sdram_conf_sem;
 
// CPU's base address
static uint32 own_hibi_base_address;
static uint32 mem_ctrl_offset;
static uint32 sdram_hibi_address;
 
// channels for receiving data from SDRAM
struct sN2H_ChannelInfo* sdram_conf_channel;
struct sN2H_ChannelInfo* sdram_data_channel;
 
/* This function is called after interrupt when mem_ctrl_offset 
   or data has been received from SDRAM */
void sdram_rx_handler(uint32* data, uint32 data_length, uint32 received_address) {
 
    if( received_address == own_hibi_base_address + SDRAM_CONF_CHANNEL_ADDR ) {
 
	mem_ctrl_offset = data[0];
	cyg_semaphore_post(&sdram_conf_sem);
 
    } else if ( received_address == own_hibi_base_address + SDRAM_DATA_CHANNEL_ADDR ) {
 
	sdram_rx_end( data, data_length/AMOUNT_UNIT_IN_BYTES );
    }
}
 
 
/* Init semaphore and reserve N2H channels for HIBI addresses */
void sdram_init(const uint32 sdram_hibi_addr) {
 
    printf("[sdram] Initializing..\n");
    sdram_hibi_address = sdram_hibi_addr;
    cyg_semaphore_init(&sdram_conf_sem, 0);
    own_hibi_base_address = GetHibiBaseAddr();
 
    sdram_conf_channel = N2H_ReserveChannel(AMOUNT_UNIT_IN_BYTES, sdram_rx_handler, 
					    false, false, SDRAM_CONF_CHANNEL_ADDR);
 
    sdram_data_channel = N2H_ReserveChannel(AMOUNT_UNIT_IN_BYTES, sdram_rx_handler, 
					    false, false, SDRAM_DATA_CHANNEL_ADDR);
 
    printf("[sdram] Initialization done!\n");
}
 
 
/* Send configuration words to SDRAM controller. */
uint32 sdram_config( const uint32 sdram_byte_addr,
		     const uint32 words,
		     const uint8  operation,
		     const uint32 read_chn_addr,
		     const uint32 row_count_and_stride) {
 
    const uint32 sdram_word_addr = ( sdram_byte_addr / AMOUNT_UNIT_IN_BYTES );
 
    uint32 cnf_addr;
    uint32 snd_amount;
    uint32 sendbuf[ SDRAM_CONFIG_SENDBUF_SIZE ];
 
    /* Adapt to read/write request */
    cnf_addr = sdram_hibi_address;
    if( operation == SDRAM_WRITE_OPERATION ) {
 
	cnf_addr = sdram_hibi_address + 1;
    }
 
    do {
 
	/* Send request (own hibi address) */
	sendbuf[ 0 ] = (own_hibi_base_address+SDRAM_CONF_CHANNEL_ADDR);
	HIBI_TX((uint8*)sendbuf, AMOUNT_UNIT_IN_BYTES, cnf_addr, HIBI_TRANSFER_TYPE_MESSAGE);
 
	/* Wait for an answer (interrupt) */
	cyg_semaphore_wait(&sdram_conf_sem);
 
    } while( mem_ctrl_offset == 0 ); /* Keep sending requests until we get 
				        legal mem_ctrl_offset value */
 
    /* Compute SDRAM configuration register base
    Base address is the same as read request address*/
    cnf_addr = sdram_hibi_address + mem_ctrl_offset;
 
    /* The two first words are always the same for reads and writes
       (SDRAM address and word count) */
    sendbuf[ SDRAM_ADDR_CONFIG ] = sdram_word_addr;
    sendbuf[ DATA_AMOUNT_CONFIG ] = words;
 
    /* Three in default, but +1 for reads */
    snd_amount = SDRAM_WRITE_CONFIG_WORDS;
 
    /* Send own hibi channel addr for read */
    if( operation == SDRAM_READ_OPERATION ) {
 
	sendbuf[ RCV_HIBI_ADDR_CONFIG ] = read_chn_addr;
	snd_amount = SDRAM_READ_CONFIG_WORDS; 
    }
 
    /* row_count_and_stride is used when reading/writing rectangular areas in memory */
    sendbuf[ snd_amount-1 ] = row_count_and_stride;
 
    /* Send config words to SDRAM controller */
    HIBI_TX((uint8*)sendbuf, snd_amount*AMOUNT_UNIT_IN_BYTES, cnf_addr, HIBI_TRANSFER_TYPE_MESSAGE);
 
    /* Return valid write address to caller */
    return cnf_addr;
 
}
 
/* This function writes data to SDRAM */
bool sdram_write( uint32* const src,
		  const uint32 sdram_addr,
		  const uint32 words ) {
 
    uint32 write_addr = 0;
 
    /* config SDRAM controller for writing */
    write_addr = sdram_config( sdram_addr, 
			       words,      
			       SDRAM_WRITE_OPERATION, 
			       0,    /* Not used when writing */
			       0 );  /* writing linear memory area */
 
    /* SDRAM configuration failed? */
    if( write_addr == 0 ) {
	return FALSE;
    }
 
    /* Send data to SDRAM controller */
    HIBI_TX((uint8*)src, words*AMOUNT_UNIT_IN_BYTES, write_addr, HIBI_TRANSFER_TYPE_DATA);
 
    return TRUE;
}
 
 
 
/* This function reads data from SDRAM (non-blocking) */
void sdram_read( const uint32 sdram_addr,
		 const uint32 words ) {
 
    /* Resize N2H channel to match the amount of data to be received */
    N2H_ResizeChannel(sdram_data_channel, words*AMOUNT_UNIT_IN_BYTES);
 
    /* configure SDRAM controller for reading */
    sdram_config( sdram_addr,
		  words,
		  SDRAM_READ_OPERATION,
		  (own_hibi_base_address+SDRAM_DATA_CHANNEL_ADDR),
		  0);            /* Reading linear memory area */
 
 
 
    /* Reading has started */
    return;
}
 
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.