URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
Compare Revisions
- This comparison shows the changes necessary to convert path
/openrisc/trunk/orpsocv2
- from Rev 373 to Rev 374
- ↔ Reverse comparison
Rev 373 → Rev 374
/sw/include/simple-spi.h
0,0 → 1,63
/* |
* Defines and prototypes for Simple SPI module driver |
* |
* Julius Baxter, julius.baxter@orsoc.se |
* |
*/ |
|
#ifndef _SIMPLE_SPI_H_ |
#define _SIMPLE_SPI_H_ |
|
#define SIMPLESPI_SPCR 0x00 // Control register |
#define SIMPLESPI_SPSR 0x01 // Status register |
#define SIMPLESPI_SPDR 0x02 // Data register |
#define SIMPLESPI_SPER 0x03 // Extensions Register |
#define SIMPLESPI_SSPU 0x04 // Slave select pickups |
|
// |
// Bit masks for each register // |
// |
|
// Control Register |
#define SIMPLESPI_SPCR_SPR 0x03 // Clock rate select |
#define SIMPLESPI_SPCR_CPHA 0x04 // Clock phase |
#define SIMPLESPI_SPCR_CPOL 0x08 // Clock polarity |
#define SIMPLESPI_SPCR_MSTR 0x10 // Master mode select |
#define SIMPLESPI_SPCR_SPE 0x40 // Serial peripheral enable (core enable) |
#define SIMPLESPI_SPCR_SPIE 0x80 // Interrupt enable |
|
// Status Register |
#define SIMPLESPI_SPSR_RFEMPTY 0x01 // Read FIFO buffer empty |
#define SIMPLESPI_SPSR_RFFULL 0x02 // Read FIFO buffer full |
#define SIMPLESPI_SPSR_WFEMPTY 0x04 // Write FIFO buffer empty |
#define SIMPLESPI_SPSR_WFFULL 0x08 // Write FIFO buffer full |
#define SIMPLESPI_SPSR_WCOL 0x40 // Write collision |
#define SIMPLESPI_SPSR_SPIF 0x80 // Interrupt flag |
|
// Extensions register |
#define SIMPLESPI_SPER_ESPR 0x03 // Extended clock rate select |
#define SIMPLESPI_SPER_ICNT 0xc0 // Interrupt count (IRQ set after no. xfer) |
|
// Pass these to the spi_core_set_int_count() function |
#define SIMPLESPI_SPER_ICNT_EVERY 0x00 |
#define SIMPLESPI_SPER_ICNT_TWO 0x40 |
#define SIMPLESPI_SPER_ICNT_THREE 0x80 |
#define SIMPLESPI_SPER_ICNT_FOUR 0xC0 |
|
|
void spi_core_enable(int core); |
void spi_core_disable(int core); |
void spi_core_interrupt_enable(int core); |
void spi_core_interrupt_disable(int core); |
void spi_core_interrupt_flag_clear(int core); |
void spi_core_clock_setup(int core, char polarity, char phase, char rate,char ext_rate); |
void spi_core_set_int_count(int core, char cnt); |
void spi_core_slave_select(int core, char slave_sel_dec); |
void spi_core_write_data(int core, char data); |
int spi_core_data_avail(int core); |
int spi_core_write_avail(int core); |
char spi_core_read_data(int core); |
|
|
|
#endif |
/sw/or1200/or1200-div.c
0,0 → 1,187
/* |
Test integer division |
|
Use a software division algorithm to perform division and compare against |
the hardware calculated results |
|
TODO: Check the signed division software calculation stuff is 100% correct! |
|
Julius Baxter, julius@opencores.org |
|
*/ |
|
#include "or32-utils.h" |
#include "uart.h" |
#include "printf.h" |
|
static int sdiv_errors, udiv_errors; |
|
#define VERBOSE_TESTS 0 |
|
// Make this bigger for running on target. For us it's enough. |
#define NUM_TESTS 200 |
|
int |
or1k_div(int dividend, int divisor) |
{ |
int result; |
asm ("l.div\t%0,%1,%2" : "=r" (result) : "r" (dividend), "r" (divisor)); |
return result; |
} |
|
unsigned int |
or1k_divu(unsigned int dividend, unsigned int divisor) |
{ |
int result; |
asm ("l.divu\t%0,%1,%2" : "=r" (result) : "r" (dividend), "r" (divisor)); |
return result; |
} |
|
|
void |
check_div(int dividend, int divisor, int expected_result) |
{ |
#if VERBOSE_TESTS |
printf("l.div 0x%.8x / 0x%.8x = 0x%.8x : ", dividend, divisor, |
expected_result); |
#endif |
int result = or1k_div(dividend, divisor); |
if ( result != expected_result) |
{ |
printf("l.div 0x%.8x / 0x%.8x = 0x%.8x : ", dividend, divisor, |
expected_result); |
|
printf("FAIL - 0x%.8x\n",result); |
sdiv_errors++; |
} |
#if VERBOSE_TESTS |
else |
printf("OK\n"); |
#endif |
|
} |
|
void |
check_divu(unsigned int dividend, unsigned int divisor, |
unsigned int expected_result) |
{ |
#if VERBOSE_TESTS |
printf("l.divu 0x%.8x / 0x%.8x = 0x%.8x : ", dividend, divisor, |
expected_result); |
#endif |
|
unsigned int result = or1k_div(dividend, divisor); |
if ( result != expected_result) |
{ |
printf("l.divu 0x%.8x / 0x%.8x = 0x%.8x : ", dividend, divisor, |
expected_result); |
|
printf("FAIL - 0x%.8x\n",result); |
udiv_errors++; |
} |
#if VERBOSE_TESTS |
else |
printf("OK\n"); |
#endif |
} |
|
|
// Software implementation of division |
unsigned int |
div_soft(unsigned int n, unsigned int d) |
{ |
|
// unsigned 32-bit restoring divide algo: |
unsigned long long p, dd; |
long long p_signed; |
unsigned int q = 0; |
|
p = (unsigned long long) n; |
dd = (unsigned long long) d << 32; |
|
int i; |
for(i=31; i>-1; i--){ |
p_signed = (2*p) - dd; |
if (p_signed>=0) |
{ |
p = (2*p) - dd; |
q |= 1 << i; |
} |
else |
{ |
p = p_signed + dd; |
} |
} |
|
return q; |
|
} |
|
int |
main(void) |
{ |
#ifdef _UART_H_ |
uart_init(DEFAULT_UART); |
#endif |
|
udiv_errors = 0; |
sdiv_errors = 0; |
|
int i; |
|
unsigned long n, d; |
unsigned long expected_result; |
i=0; |
while(i < NUM_TESTS) |
{ |
n = rand(); |
d = rand(); |
|
|
while ( d >= n ) |
d >>= (rand() & 0xff); |
|
if (n&0x80000000) // numerator is negative |
{ |
// Calculate a value that's really smaller than the numerator |
while ( d >= ~(n-1) ) |
d >>= (rand() & 0xff); |
// Processor thinks it's in 2's complement already, so we'll convert |
// from the interpreted 2's complement to unsigned for our calculation |
expected_result = div_soft(~(n-1), d); |
// Answer will be an unsigned +ve value, but of course it has to be |
// negative so convert back to 2's complment negative |
expected_result = ~expected_result + 1; // 2's complement |
} |
else |
expected_result = div_soft(n, d); |
|
check_div(n, d, expected_result); |
|
n >>= 1; |
|
while ( d >= n ) |
d >>= (rand() & 0xff); |
|
expected_result = div_soft(n, d); |
check_divu(n, d, expected_result); |
i++; |
//printf("%d\n",i); |
|
} |
|
|
printf("Division check complete\n"); |
printf("Unsigned:\t%d tests\t %d errors\n", |
NUM_TESTS, udiv_errors); |
printf("Signed:\t\t%d tests\t %d errors\n", |
NUM_TESTS, sdiv_errors); |
|
if ((udiv_errors > 0) || (sdiv_errors > 0)) |
report(0xbaaaaaad); |
else |
report(0x8000000d); |
|
return 0; |
|
} |
/sw/support/simple-spi.c
0,0 → 1,100
/* |
* Simple SPI module driver |
* |
* Julius Baxter, julius.baxter@orsoc.se |
* |
*/ |
|
#include "board.h" |
#include "simple-spi.h" |
#include "or32-utils.h" |
|
const int spi_base_adr[1] = {SPI0_BASE}; |
|
void spi_core_enable(int core) |
{ |
REG8((spi_base_adr[core] + SIMPLESPI_SPCR)) |= SIMPLESPI_SPCR_SPE; |
} |
|
void spi_core_disable(int core) |
{ |
REG8((spi_base_adr[core] + SIMPLESPI_SPCR)) &= ~SIMPLESPI_SPCR_SPE; |
} |
|
void spi_core_interrupt_enable(int core) |
{ |
REG8((spi_base_adr[core] + SIMPLESPI_SPCR)) |= SIMPLESPI_SPCR_SPIE; |
} |
|
void spi_core_interrupt_disable(int core) |
{ |
REG8((spi_base_adr[core] + SIMPLESPI_SPCR)) &= ~SIMPLESPI_SPCR_SPIE; |
} |
|
void spi_core_interrupt_flag_clear(int core) |
{ |
REG8((spi_base_adr[core] + SIMPLESPI_SPSR)) = SIMPLESPI_SPSR_SPIF; |
} |
|
void spi_core_clock_setup(int core, char polarity, char phase, char rate, |
char ext_rate) |
{ |
char spcr = REG8((spi_base_adr[core] + SIMPLESPI_SPCR)); |
|
if (polarity) |
spcr |= SIMPLESPI_SPCR_CPOL; |
else |
spcr &= ~SIMPLESPI_SPCR_CPOL; |
|
if (phase) |
spcr |= SIMPLESPI_SPCR_CPHA; |
else |
spcr &= ~SIMPLESPI_SPCR_CPHA; |
|
spcr = (spcr & ~SIMPLESPI_SPCR_SPR) | (rate & SIMPLESPI_SPCR_SPR); |
|
REG8((spi_base_adr[core] + SIMPLESPI_SPCR)) = spcr; |
|
char sper = REG8((spi_base_adr[core] + SIMPLESPI_SPER)); |
|
sper = (sper & ~SIMPLESPI_SPER_ESPR) | (ext_rate & SIMPLESPI_SPER_ESPR); |
|
REG8((spi_base_adr[core] + SIMPLESPI_SPER)) = sper; |
|
} |
|
void spi_core_set_int_count(int core, char cnt) |
{ |
char sper = REG8((spi_base_adr[core] + SIMPLESPI_SPER)); |
|
sper = (sper & ~SIMPLESPI_SPER_ICNT) | cnt; |
|
REG8((spi_base_adr[core] + SIMPLESPI_SPER)) = sper; |
|
} |
// slave_sel_dec is decoded (so asserted bit in right place) |
void spi_core_slave_select(int core, char slave_sel_dec) |
{ |
REG8((spi_base_adr[core] + SIMPLESPI_SSPU)) = slave_sel_dec; |
} |
|
int spi_core_data_avail(int core) |
{ |
return !!!(REG8((spi_base_adr[core]+SIMPLESPI_SPSR))&SIMPLESPI_SPSR_RFEMPTY); |
} |
|
int spi_core_write_avail(int core) |
{ |
return !!!(REG8((spi_base_adr[core]+SIMPLESPI_SPSR))&SIMPLESPI_SPSR_WFFULL); |
} |
|
// Should call spi_core_write_avail() before calling this, we don't check |
void spi_core_write_data(int core, char data) |
{ |
REG8((spi_base_adr[core] + SIMPLESPI_SPDR)) = data; |
} |
|
char spi_core_read_data(int core) |
{ |
return REG8((spi_base_adr[core] + SIMPLESPI_SPDR)); |
} |