⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mqspi.c

📁 A few drivers for the Motorola C380 s celluar phone hardware with a simple test application. It s co
💻 C
字号:
/*
   Neptune LTE Multiple-Queue SPI driver
   ----------------------------
   (c) motoprogger 2008
*/

#include "../libs/motolibs.h"
#include "watchdog.h"
#include "gpio.h"
#include "mqspi.h"
typedef struct
{
        hword configA;
        hword configB;
} MQSPI_CSCFG;

typedef struct
{
        hword statusA;
        hword statusB;
} MQSPI_QST;

typedef struct
{
        hword queueA;
        hword queueB;
        hword queueC;
} MQSPI_FQ;

typedef struct
{
        hword pointer;
        hword mode;
} MQSPI_SPICD;

#define MQSPI_BASE 0x24851000
#define MQSPI_MCON_REGISTER hword_ptr(MQSPI_BASE+0x000)
#define MQSPI_QCFG_L_REGISTER hword_ptr(MQSPI_BASE+0x002)
#define MQSPI_QCFG_H_REGISTER hword_ptr(MQSPI_BASE+0x004)
#define MQSPI_MTRIG_REGISTER hword_ptr(MQSPI_BASE+0x006)
#define MQSPI_STPR_L_REGISTER hword_ptr(MQSPI_BASE+0x008)
#define MQSPI_STPR_H_REGISTER hword_ptr(MQSPI_BASE+0x00A)
#define MQSPI_SDEF_REGISTER hword_ptr(MQSPI_BASE+0x00C)
#define MQSPI_SFLG_REGISTER hword_ptr(MQSPI_BASE+0x00E)
#define MQSPI_SFLG_REGISTER hword_ptr(MQSPI_BASE+0x00E)
#define MQSPI_SPIM_REGISTER hword_ptr(MQSPI_BASE+0x010)
#define MQSPI_STFF_L_REGISTER hword_ptr(MQSPI_BASE+0x012)
#define MQSPI_STFF_H_REGISTER hword_ptr(MQSPI_BASE+0x014)
#define MQSPI_STFE_L_REGISTER hword_ptr(MQSPI_BASE+0x016)
#define MQSPI_STFE_H_REGISTER hword_ptr(MQSPI_BASE+0x018)
#define MQSPI_QRE_L_REGISTER hword_ptr(MQSPI_BASE+0x01A)
#define MQSPI_QRE_H_REGISTER hword_ptr(MQSPI_BASE+0x01C)
#define MQSPI_SDI_MD_L_REGISTER hword_ptr(MQSPI_BASE+0x01E)
#define MQSPI_SDI_MD_H_REGISTER hword_ptr(MQSPI_BASE+0x020)
#define MQSPI_CDPS1_REGISTER hword_ptr(MQSPI_BASE+0x022)
#define MQSPI_CDMS1_REGISTER hword_ptr(MQSPI_BASE+0x024)
#define MQSPI_CDPS2_REGISTER hword_ptr(MQSPI_BASE+0x026)
#define MQSPI_CDMS2_REGISTER hword_ptr(MQSPI_BASE+0x028)
#define MQSPI_CSCFG_REGISTERS ((volatile MQSPI_CSCFG * ) ((void * ) (MQSPI_BASE+0x02A)))
#define MQSPI_QST_REGISTERS (MQSPI_QST * ) ((void * ) (MQSPI_BASE+0x052))
#define MQSPI_SST_REGISTER hword_ptr(MQSPI_BASE+0x05A)
#define MQSPI_FQ_REGISTERS (MQSPI_FQ * ) ((void * ) (MQSPI_BASE+0x05C))
#define MQSPI_CONTROL_DATA_RAM ((MQSPI_SPICD * ) ((void * ) (MQSPI_BASE+0x400)))
#define MQSPI_IO_DATA_RAM ((hword * ) ((void * ) (MQSPI_BASE+0x480)))

#define set_bit(hw_l,hw_h,bit,cond) { \
        hword reg,mask; \
        mask=1<<(bit&15); \
        if (bit<16) reg=hw_l; \
        else reg=hw_h; \
        if (!(cond)) reg&=~mask; \
        else reg|=mask; \
        if (bit<16) hw_l=reg; \
        else hw_h=reg; \
}

#define block_hword_offset(block) (block<<4)

word triggers;
hword mem_blocks; /* 32 bytes each, 512 bytes => 16 blocks */
word trig_assign[64]; /* 0-31 for write, 32-63 for read, 255=no block assigned */
hword bus_sel; /* A bus select bit per chip-select */

void mqspi_reset(byte bus)
{
        hword mask;
        byte i;
        switch(bus)
        {
        case MQSPI_BUS_ALL:
                mask=4;
                break;
        case MQSPI_BUS_1:
                mask=2;
                break;
        case MQSPI_BUS_2:
                mask=1;
                break;
        default:
                mask=0;
                break;
        }
        MQSPI_MCON_REGISTER|=mask;
        while(MQSPI_MCON_REGISTER&mask);
        if (bus==MQSPI_BUS_ALL)
        {
                triggers=0;
                mem_blocks=0;
                for (i=0; i<64; i++) trig_assign[i]=255;
        }
}

void mqspi_enable(byte bus, bool enable)
{
        hword mask,cr;
        cr=MQSPI_MCON_REGISTER;
        switch(bus)        {
        case MQSPI_BUS_ALL:
                mask=0x20;
                break;
        case MQSPI_BUS_1:
                mask=0x10;
                break;
        case MQSPI_BUS_2:
                mask=8;
                break;
        default:
                mask=0;
                break;
        }
        if (enable) cr|=mask;
        else cr&=~mask;
        MQSPI_MCON_REGISTER=cr;
}

void mqspi_configure_cs(byte cs, byte bus, byte clkdiv, byte flags, byte dat, byte dbt)
{
        if (cs<10 && bus==MQSPI_BUS_1 || bus==MQSPI_BUS_2)
        {
                MQSPI_CSCFG_REGISTERS[cs].configA=((clkdiv-1)&0x7f)<<5|flags&MQSPI_CSCFG_FLAGS_MASK;
                MQSPI_CSCFG_REGISTERS[cs].configB=(dat&0x7f)<<7|dbt&0x7f;
                if (bus==MQSPI_BUS_1) bus_sel&=~(1<<cs);
                else bus_sel|=1<<cs;                
        }
}

byte mqspi_get_trigger()
{
        byte i;
        for (i=0; i<32; i++)
        {
                if (!(triggers&1<<i))
                {
                        triggers|=1<<i;
                        return i;
                }
        }
        return 255;
}

void mqspi_trigger_config(byte trigger, byte priority, byte count, byte cs)
{
        hword reg;
        if (trigger<32 && (triggers&1<<trigger) && priority==MQSPI_PRIORITY_NORMAL ||         priority==MQSPI_PRIORITY_HIGH && count>0 && count<=64 && cs<10)
        {
                set_bit(MQSPI_STPR_L_REGISTER,MQSPI_STPR_H_REGISTER,trigger,priority==MQSPI_PRIORITY_HIGH);
                reg=MQSPI_CONTROL_DATA_RAM[trigger].mode;
                reg&=0x1F0;
                reg|=cs&0xF|((count-1)&0x3F)<<9;
                MQSPI_CONTROL_DATA_RAM[trigger].mode=reg;
        }                
}

byte mqspi_alloc()
{	word i;
        for (i=0; i<16; i++)
                if (!(mem_blocks&1<<i))
                {
                        mem_blocks|=1<<i;
                        return i;
                }
        return 255;
}

void mqspi_free(byte block)
{
        mem_blocks&=~(1<<block);
}
         
void mqspi_trigger_free_buffs(byte trigger)
{
        if (trig_assign[trigger]!=255)\
        {
                mqspi_free(trig_assign[trigger]);
                trig_assign[trigger]=255;
        }
        if (trig_assign[trigger+32]!=255)
        {
                mqspi_free(trig_assign[trigger+32]);
                trig_assign[trigger+32]=255;
        }
}

bool mqspi_trigger_alloc_buffs(byte trigger,bool read)
{
        byte wbuf,rbuf;
        mqspi_trigger_free_buffs(trigger);
        wbuf=mqspi_alloc();
        if (wbuf==255) return false;
        if (read)
        {
                rbuf=mqspi_alloc();
                if (rbuf==255)
                {
                        mqspi_free(wbuf);
                        return false;
                }
        }
        else rbuf=255;
        trig_assign[trigger]=wbuf;
        trig_assign[trigger+32]=rbuf;
        return true;
}
        
bool mqspi_trigger_assign_data(byte trigger, hword * data, byte msglen, bool read)
{
        if (trigger<32 && triggers&(1<<trigger) && msglen>0 && msglen<=32)
        {
                hword i,reg,wbase,rbase;
                wbase=trigger<<4;
                set_bit(MQSPI_QRE_L_REGISTER,MQSPI_QRE_H_REGISTER,trigger,read);
                if (!mqspi_trigger_alloc_buffs(trigger,read)) return false;
                wbase=block_hword_offset(trig_assign[trigger]);
                if (read) rbase=block_hword_offset(trig_assign[trigger+32]);
                else rbase=0;
                MQSPI_CONTROL_DATA_RAM[trigger].pointer=wbase<<8|rbase;
                reg=MQSPI_CONTROL_DATA_RAM[trigger].mode;
                reg&=~0x1F0;
                reg|=(msglen-1)<<4;
                for (i=0; i<(msglen+1)>>1; i++) MQSPI_IO_DATA_RAM[wbase+i]=data[i];
                return true;
        }
        return false;
}

void mqspi_trigger_activate(byte trigger)
{
        if (trigger<0x20)
        {
                MQSPI_MTRIG_REGISTER=trigger&0x1f|0x20;
                if (trigger<0x10) MQSPI_STFF_L_REGISTER=1<<trigger;
                else MQSPI_STFF_H_REGISTER=1<<(trigger-0x10);
        }
}

bool mqspi_trigger_check_busy(byte trigger)
{
        if (trigger<0x20)
        {
                if (trigger<0x10) return !(MQSPI_STFF_L_REGISTER&(1<<trigger));
                else return !(MQSPI_STFF_H_REGISTER&(1<<(trigger-0x10)));
        }
        return false;
}

void mqspi_trigger_wait(byte trigger)
{
        while(mqspi_trigger_check_busy) wdog_service();
}

bool mqspi_trigger_fetch_data(byte trigger, hword * data)
{
        byte rbase,msglen,i;
        if (trigger<32 && trig_assign[trigger+0x20]!=255)
        {
                rbase=MQSPI_CONTROL_DATA_RAM[trigger].pointer&0xff;
                msglen=MQSPI_CONTROL_DATA_RAM[trigger].mode>>4&0x1f+1;
                for (i=0; i<(msglen+1)>>1; i++) data[i]=MQSPI_IO_DATA_RAM[rbase+i];
                return true;
        }
        return false;
}

void mqspi_trigger_free(byte trigger)
{
        mqspi_trigger_free_buffs(trigger);
        triggers&=~(1<<trigger);
}

bool mqspi_transcieve(hword *wdata, hword *rdata, byte length, byte cs, byte count, byte priority)
{
        byte trig;
        trig=mqspi_get_trigger();
        if (trig==255) return false;
        mqspi_trigger_config(trig,priority,count,cs);
        if (!mqspi_trigger_assign_data(trig,wdata,length,rdata!=0)) 
        {
                mqspi_trigger_free(trig);
                return false;
        }
        mqspi_trigger_activate(trig);
        mqspi_trigger_wait(trig);
        if (rdata!=0) mqspi_trigger_fetch_data(trig,rdata);
        mqspi_trigger_free(trig);
        return true;
}

void mqspi_init()
{
        /* TODO: write init */
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -