LPP_spwAPI.c
176 lines
| 5.2 KiB
| text/x-c
|
CLexer
/ src / LPP_spwAPI.c
paul
|
r0 | #include <..\header\LPP_spwAPI.h> | ||
#include <stdlib.h> | ||||
#include <stdio.h> | ||||
volatile int *lreg = (int*) 0x80000200; // the IRQMP controller registers are at 0x80000200 | ||||
inline int loadmemAPI(int addr) | ||||
{ | ||||
int tmp; | ||||
asm volatile (" lda [%1]1, %0 " // LDA => Load Word from Alternate space | ||||
: "=r" (tmp) | ||||
: "r" (addr) | ||||
); | ||||
return tmp; | ||||
} | ||||
inline char loadb(int addr) | ||||
{ | ||||
char tmp; | ||||
asm volatile (" lduba [%1]1, %0 " | ||||
: "=r" (tmp) | ||||
: "r" (addr) | ||||
); | ||||
return tmp; | ||||
} | ||||
char *almalloc(int sz) | ||||
{ | ||||
char *tmp; | ||||
tmp = (char*) malloc(2*sz); | ||||
tmp = (char*) (((int)tmp+sz) & ~(sz-1)); | ||||
return(tmp); | ||||
} | ||||
////// | ||||
// SPW | ||||
////// | ||||
void spw_reset(grspwregs_t *regs) | ||||
{ | ||||
regs->ctrl = GRSPW_CTRL_RS; // make complete reset of the spacewire node, self clearing | ||||
} | ||||
void spw_init(int nodeaddr, int clkdiv, int destkey, int rxmaxlen, grspwregs_t *regs) | ||||
{ | ||||
regs->ctrl = GRSPW_CTRL_LS | GRSPW_CTRL_RE; // link start (LS) | ||||
// RMAP enable (RE) | ||||
regs->ctrl = GRSPW_CTRL_LS | GRSPW_CTRL_RE; | ||||
regs->ctrl = GRSPW_CTRL_LS | GRSPW_CTRL_RE; | ||||
regs->ctrl = GRSPW_CTRL_LS | GRSPW_CTRL_RE; | ||||
regs->ctrl = GRSPW_CTRL_LS | GRSPW_CTRL_RE; | ||||
regs->ctrl = GRSPW_CTRL_LS | GRSPW_CTRL_RE; | ||||
regs->status = 0xffffffff; | ||||
regs->nodeaddr = nodeaddr; | ||||
regs->clkdiv = clkdiv; | ||||
regs->destkey = destkey; | ||||
regs->time = 0; | ||||
regs->dmactrl = GRSPW_DMACTRL_RA | GRSPW_DMACTRL_TA | GRSPW_DMACTRL_PR | GRSPW_DMACTRL_PS | GRSPW_DMACTRL_AI; | ||||
regs->rxmaxlen = rxmaxlen; | ||||
regs->txdesc = 0; | ||||
regs->rxdesc = 0; | ||||
} | ||||
void set_txd(char *dataAddress, unsigned int dataLength, char *headerAddress, unsigned int headerLength, volatile int *txd) | ||||
{ | ||||
txd[4] = 0; | ||||
txd[3] = (int) dataAddress; // data address | ||||
txd[2] = dataLength; // data length | ||||
txd[1] = (int) headerAddress; // header address | ||||
txd[0] = (1 << 13) | (1 << 12) | headerLength; // bit 13 WR = 1 next descriptor read will be 1st one in the table (at the base address) | ||||
// bit 12 EN = 1 enable transmitter descriptor | ||||
// bit 0 to 7 stand for the header length | ||||
} | ||||
int spw_checkrx(int* size, volatile int *rxd, grspwregs_t *regs) | ||||
{ | ||||
volatile int tmp = 0; | ||||
tmp = regs->dmactrl; | ||||
if ( ( (tmp >> 6) & 1 ) ) | ||||
{ // bit 6 PR packet received | ||||
*size = loadmemAPI((int) &rxd[0]) & 0x00001fff; | ||||
regs->dmactrl = regs->dmactrl | 1 << 6; // clear bit 6 PR (packet received) by writing a one | ||||
return 1; | ||||
} | ||||
else return 0; | ||||
} | ||||
int spw_checktx(grspwregs_t *regs) | ||||
{ | ||||
if ( ( (regs->dmactrl >> 5) & 1 )==1 ) | ||||
{ // bit 5 PS (packet sent), cleared when written with a one | ||||
regs->dmactrl = regs->dmactrl | 1 << 5; // clear bit 5 PS (packet sent) by writing a one | ||||
return 1; | ||||
} | ||||
else return 0; | ||||
} | ||||
void enable_transmitter_descriptor(unsigned int headerLength, volatile int *txd) | ||||
{ | ||||
txd[0] = GRSPW_TXBD_WR | GRSPW_TXBD_EN; | ||||
//WR = 1 next descriptor read will be 1st one in the table (at the base address) | ||||
//EN = 1 enable transmitter descriptor | ||||
} | ||||
void enable_transmitter(grspwregs_t *regs) | ||||
{ | ||||
regs->dmactrl = regs->dmactrl | GRSPW_DMACTRL_TE; | ||||
} | ||||
void enable_receiver_descriptor(volatile char *rx, volatile int *rxd) | ||||
{ | ||||
rxd[1] = (int) rx; | ||||
rxd[0] = GRSPW_RXBD_IE | GRSPW_RXBD_WR | GRSPW_RXBD_EN; | ||||
// IE = 1 Interrupt enable | ||||
// WR = 1 next descriptor will be the 1st one in the desc table (at the base address) | ||||
// EN = 1 activate the descriptor | ||||
} | ||||
void enable_receiver(grspwregs_t *regs) | ||||
{ | ||||
regs->dmactrl = regs->dmactrl | 1 << 11 | 1 << 2; | ||||
} | ||||
int enable_timecode_reception(grspwregs_t *regs) | ||||
{ | ||||
regs->ctrl = regs->ctrl | GRSPW_CTRL_TR; | ||||
return 1; | ||||
} | ||||
int check_time(grspwregs_t *grspw_regs) | ||||
{ | ||||
int tmp = loadmemAPI((int)&(grspw_regs->status)) & 1; | ||||
if (tmp) { | ||||
grspw_regs->status = loadmemAPI((int)&(grspw_regs->status)) | 1; | ||||
} | ||||
return tmp; | ||||
} | ||||
////////////// | ||||
// GENERAL USE | ||||
////////////// | ||||
void send_fine_time(unsigned int fine_time){ | ||||
spacewire_PARAMETERS.tx[0] = (char) fine_time; // send the fine time value to LPPMON | ||||
spacewire_PARAMETERS.tx[1] = (char) (fine_time>>8); | ||||
spacewire_PARAMETERS.tx[2] = (char) (fine_time>>16); | ||||
spacewire_PARAMETERS.tx[3] = (char) (fine_time>>24); | ||||
enable_transmitter_descriptor(HEADERLEN, spacewire_PARAMETERS.txd); // enable the descriptor for transmission | ||||
enable_transmitter(spacewire_PARAMETERS.regs); // enable the transmission | ||||
} | ||||
////// | ||||
// IRQ | ||||
////// | ||||
int irqhandler_receive_CCSDS(int irq, void * args, struct leonbare_pt_regs * leon_regs) | ||||
{ | ||||
if (spw_checkrx(spacewire_PARAMETERS.size, spacewire_PARAMETERS.rxd, spacewire_PARAMETERS.regs)==1) | ||||
{ | ||||
packet_type.time_packet = 1; | ||||
return 1; | ||||
} | ||||
return 0; | ||||
} | ||||
int enable_irq(int irq) | ||||
{ | ||||
lreg[ICLEAR/4] = (1 << irq); // clear any pending irq | ||||
lreg[IMASK/4] = lreg[IMASK/4] | (1 << irq); // unmask irq | ||||
return 1; | ||||
} | ||||
int disable_irq(int irq) { lreg[IMASK/4] &= ~(1 << irq); return 1;} | ||||
int force_irq(int irq) { lreg[IFORCE/4] = lreg[IFORCE/4] | (1 << irq); return 1;} | ||||