world leader in high performance signal processing
Trace: » hardware

Hardware specific programming with ELF GCC

This page throws some hardware specific examples / functions for Blackfin with GCC ELF toolchain. Please refer to Blackfin Documents for more information on the peripherals and MMR control settings. Only basic ideas are provided here, for users who are totally new to Blackfin. The Visual DSP++ examples available here Code Examples and with their installation directory can be easily ported to GCC environment, provided the user is aware of the differences explained in the main page.

An LED blink example

This is a simple LED blink example on BF537 EZ-KIT. The code terminates when PB1 button is pressed. Almost all MMRs and bit definitions should be included through “cdefBF37.h”. Builtin APIs such as SSYNC() will be included through “gcc.h”.

#include <cdefBF537.h>
#include <gcc.h>
int main();
void pf_isr(void) __attribute__((interrupt_handler));
volatile int PB1 = 0;
int i;
 
int main(void)
{
	*pPORTF_FER 		= 0;										   // GPIO initialize as Flags
	*pPORTFIO_DIR		= PF6 | PF7 | PF8 | PF9 | PF10 | PF11;// Set direction as output for LEDs
	*pPORTFIO_SET		= PF6 | PF7 | PF8 | PF9 | PF10 | PF11;// Turn all LEDs on
	*pPORTFIO_INEN 		= PF2;										   // set direction as input for push button
	*pPORTFIO_EDGE      = PF2;										   // Set as edge sensitive interrupt
	*pPORTFIO_MASKA_SET = PF2;										   // Enable Mask A for Port F interrupt
	ssync();
 
	*pSIC_IMASK = IRQ_PFA_PORTFG; 			              // enable FlagA interrupt
	ssync();
	*pEVT12 = pf_isr; 												   // assign ISR to interrupt vector
	ssync();
	asm volatile ("cli %0; bitset (%0, 12); sti %0; csync;": "+d"(i)); // set IMASK bit
 
	while(!PB1)
	{
			*pPORTFIO_CLEAR		= PF6 | PF7 | PF8 | PF9 | PF10 | PF11;
 
			for(i=0;i<1000000;i++)
			{asm("NOP;");}
 
			*pPORTFIO_SET		= PF6 | PF7 | PF8 | PF9 | PF10 | PF11;
 
			for(i=0;i<1000000;i++)
			{asm("NOP;");}
 
	}
 
	return 0;
}
 
__attribute__((interrupt_handler))
void pf_isr(void)
{
	PB1 = 1;
 
	*pPORTFIO_CLEAR = PF2;												 // clear interrupt handling
	ssync();
}

LED blinking on SDP

A simple code for blinking LEDs in System Development Platform (SDP) board:

SDP_LED_Blink.c
#include <cdefBF527.h>
 
typedef unsigned char u8;
u8 latchValue = 0;
 
#define PIN_PG0 1
 
void writeToSdpLatch(u8 latchData);
void flashLed(void);
void waitfunc(void);
void configEBIU(void);
void configPF(void);
 
int main()
{
	configPF();
	configEBIU();
 
	while(1)
	{
		flashLed();
 
	}
 
	return 0;
 
}
//-----------------------------------------------------------------------------
void configPF()
{
	*pPORTGIO_DIR |= PIN_PG0;
	*pPORTGIO_SET = PIN_PG0;
	asm("SSYNC;");
 
}
 
 
//-----------------------------------------------------------------------------
void configEBIU()
{
	*pEBIU_AMGCTL  = 0x00F9;
	*pEBIU_AMBCTL0 = 0x7BB07BB0;
	*pEBIU_AMBCTL1 = 0x7BB07BB0;
	asm("SSYNC;");
 
}
 
//-----------------------------------------------------------------------------
void writeToSdpLatch(u8 latchData)
{
 
	// write to latch (bank 2)
	*((u8*)0x20200000) = latchData;
	asm("SSYNC;");
}
 
//-----------------------------------------------------------------------------
void flashLed(void)
{
	u8 i = 0;
 
	for (i=0; i<5; i++)
	{
		latchValue = latchValue | 0x08;
		writeToSdpLatch(latchValue);
		waitfunc();
		latchValue = latchValue & 0xF7;
		writeToSdpLatch(latchValue);
		waitfunc();
	}
}
 
//-----------------------------------------------------------------------------
void waitfunc()
{
	int j = 0;
 
	for(j=0;j<2000000;j++)
	asm("NOP;");
}

Enabling MDMA

#include <cdefbf537.h>
#include <gcc.h>
#define BUFFERSIZE 16
 
void pf_isr() __attribute__((interrupt_handler));
void setup_interrupts();
void setup_memDMA();
 
int i;
volatile unsigned int cnt = 0;
volatile char source_buf[BUFFERSIZE] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
volatile char destination_buf[BUFFERSIZE];
 
int main()
{
	setup_interrupts();						//Initialize interrupts
	setup_memDMA();							//Configure memDMA MMRs
 
	while(1)								//Infinite loop
	{
		asm("NOP;");
	}
 
	return 0;
}
 
/********************************************************
Configure and setup memDMA
********************************************************/
 
void setup_memDMA()
{
	//Source registers
	*pMDMA_S0_CONFIG = FLOW_STOP  ;				//Stop mode
	*pMDMA_S0_START_ADDR = &source_buf;			//Starting address
	*pMDMA_S0_X_COUNT = BUFFERSIZE;				//DMA count
	*pMDMA_S0_Y_COUNT = 0x0000;
	*pMDMA_S0_X_MODIFY = 0x0001;
	*pMDMA_S0_Y_MODIFY = 0x0000;
	ssync();
 
	//Destination registers
	*pMDMA_D0_CONFIG = FLOW_STOP | DI_EN |WNR;  //Stop mode, allow interrupt after completion, mem write
	*pMDMA_D0_START_ADDR = &destination_buf;	//Starting address
	*pMDMA_D0_X_COUNT = BUFFERSIZE;				//DMA count
	*pMDMA_D0_Y_COUNT = 0x0000;
	*pMDMA_D0_X_MODIFY = 0x0001;
	*pMDMA_D0_Y_MODIFY = 0x0000;
	ssync();
 
	//enable memDMA
	*pMDMA_S0_CONFIG |= DMAEN;
	ssync();
	*pMDMA_D0_CONFIG |= DMAEN;
	ssync();
}
 
/********************************************************
Initialize interrupts
********************************************************/
 
void setup_interrupts()
{
	*pEVT13 = pf_isr; 							//setup ISR for ivg 13 memDMA interrupt
	ssync();
	*pSIC_IMASK =IRQ_DMA13;   			        //unmask memDMA interrupt
	ssync();
	asm volatile ("cli %0; bitset (%0, 13); sti %0; csync;": "+d"(i)); // set IMASK bit
}
 
/********************************************************
Interrupt service routine for memDMA interrupt
********************************************************/
 
__attribute__((interrupt_handler))
void pf_isr()
{
	//clear interrupts
	*pMDMA_D0_IRQ_STATUS |= DMA_DONE;
	ssync();
 
	cnt++;								        	//increment counter
}

Configuring PLL & SDRAM Controller

SDRAM Controller is usually configured prior to using (or accessing) the SDRAM. The timings must be derived from the SCLK frequency and must match the SDRAM datasheet specifications.

For PLL settings, please read the Hardware Manual carefully.

file: trunk/examples/standalone/bf537-stamp/sdc-cplb-init/init.c

scm failed with exit code 1:
file does not exist in git

Enabling Cache and CPLBs

Cache and CPLB settings are explained well in the Hardware Manual as well as in this Application Note: Cache on Blackfin . The Processor can hold up to 16 entries of CPLBs (each defining protection and cache properties). If there is an access outside the define memory blocks, an entry is replaced by the entry pertaining to faulty block.

file: trunk/examples/standalone/bf537-stamp/sdc-cplb-init/cplb.c

scm failed with exit code 1:
file does not exist in git