예제 #1
0
void AT91_SPI_Driver::Uninitialize()
{
    NATIVE_PROFILE_HAL_PROCESSOR_SPI();
    // Do not disable the Periperal clock, as it is used for LCD 
    for(int i = 0; i < AT91_SPI::c_MAX_SPI; i++)
    {
        if(g_AT91_SPI_Driver.m_initialized[i] == TRUE)
        {
            AT91_SPI &spi = AT91::SPI(i);

            spi.SPI_CR |= AT91_SPI::SPI_CR_DISABLE_SPI; //Disable SPI Module, don't care the other bit.

            g_AT91_SPI_Driver.m_initialized[i] = FALSE;
        }
    }
	
    AT91_PMC &pmc = AT91::PMC();
	
    pmc.DisablePeriphClock(AT91C_ID_SPI0);

#if (AT91C_MAX_SPI == 2)
     pmc.DisablePeriphClock(AT91C_ID_SPI1);
#endif


	   
}
예제 #2
0
BOOL MC9328MXL_SPI_Driver::Initialize()
{
    NATIVE_PROFILE_HAL_PROCESSOR_SPI();

    // Start by disabling the modules, since it does not happen on reset
    for (int i=0; i<MC9328MXL_SPI::c_MAX_SPI; i++)
    {
        if(g_MC9328MXL_SPI_Driver.m_initialized[i] == FALSE)
        {
            MC9328MXL::SPI(i).CONTROLREG &= (~MC9328MXL_SPI::CONTROLREG_SPIEN);     //Disable SPI Module, don't care the other bit.

            g_MC9328MXL_SPI_Driver.m_initialized[i] = TRUE;
        }
    }

    // set up the GPIOs, always set them in the right state, as some other peripheral could have stolen them

    // should not put the SPI pins to any state, as it is unknown what user has connected it to.
    // put pins as in input would be the safest state.
    // SPI 1
    CPU_GPIO_EnableInputPin( MC9328MXL_SPI::c_SPI1_SCLK, FALSE, NULL, GPIO_INT_NONE, RESISTOR_PULLUP );
    CPU_GPIO_EnableInputPin( MC9328MXL_SPI::c_SPI1_MISO, FALSE, NULL, GPIO_INT_NONE, RESISTOR_PULLUP );
    CPU_GPIO_EnableInputPin( MC9328MXL_SPI::c_SPI1_MOSI, FALSE, NULL, GPIO_INT_NONE, RESISTOR_PULLUP );

#if !defined(PLATFORM_ARM_MC9328MXS)
    // SPI 2
    CPU_GPIO_EnableInputPin( MC9328MXL_SPI::c_SPI2_SCLK, FALSE, NULL, GPIO_INT_NONE, RESISTOR_PULLUP );
    CPU_GPIO_EnableInputPin( MC9328MXL_SPI::c_SPI2_MISO, FALSE, NULL, GPIO_INT_NONE, RESISTOR_PULLUP );
    CPU_GPIO_EnableInputPin( MC9328MXL_SPI::c_SPI2_MOSI, FALSE, NULL, GPIO_INT_NONE, RESISTOR_PULLUP );
#endif

    return TRUE;
}
예제 #3
0
void CPU_SPI_Uninitialize()
{
    NATIVE_PROFILE_HAL_PROCESSOR_SPI();
    RCC->APB2ENR &= ~RCC_APB2ENR_SPI1EN; // disable SPI clocks
    RCC->APB1ENR &= ~RCC_APB1ENR_SPI2EN;
    RCC->APB1ENR &= ~RCC_APB1ENR_SPI3EN;
}
예제 #4
0
BOOL CPU_SPI_Initialize()
{
    NATIVE_PROFILE_HAL_PROCESSOR_SPI();
    RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; // enable SPI clocks
    RCC->APB1ENR |= RCC_APB1ENR_SPI2EN;
    RCC->APB1ENR |= RCC_APB1ENR_SPI3EN;
    return TRUE;
}
예제 #5
0
void MC9328MXL_SPI_Driver::Uninitialize()
{
    NATIVE_PROFILE_HAL_PROCESSOR_SPI();
    // Do not disable the Periperal clock, as it is used for LCD
    for (int i=0; i<MC9328MXL_SPI::c_MAX_SPI; i++)
    {
        if(g_MC9328MXL_SPI_Driver.m_initialized[i] == TRUE)
        {
            MC9328MXL::SPI(i).CONTROLREG &= (~MC9328MXL_SPI::CONTROLREG_SPIEN);     //Disable SPI Module, don't care the other bit.

            g_MC9328MXL_SPI_Driver.m_initialized[i] = FALSE;
        }
    }
}
BOOL CPU_SPI_nWrite8_nRead8( const SPI_CONFIGURATION& Configuration, UINT8* Write8, INT32 WriteCount, UINT8* Read8, INT32 ReadCount, INT32 ReadStartOffset )
{
    NATIVE_PROFILE_HAL_PROCESSOR_SPI();
    if(!CPU_SPI_Xaction_Start( Configuration )) return FALSE;
    SPI_XACTION_8 Transaction;
    Transaction.Read8           = Read8;
    Transaction.ReadCount       = ReadCount;
    Transaction.ReadStartOffset = ReadStartOffset;
    Transaction.Write8          = Write8;
    Transaction.WriteCount      = WriteCount;
    Transaction.SPI_mod         = Configuration.SPI_mod;
    if(!CPU_SPI_Xaction_nWrite8_nRead8( Transaction )) return FALSE;
    return CPU_SPI_Xaction_Stop( Configuration );
}
예제 #7
0
BOOL AT91_SPI_Driver::Xaction_Start(const SPI_CONFIGURATION &Configuration)
{
    NATIVE_PROFILE_HAL_PROCESSOR_SPI();
    
    if(!g_AT91_SPI_Driver.m_Enabled[Configuration.SPI_mod])
    {
        g_AT91_SPI_Driver.m_Enabled[Configuration.SPI_mod] = TRUE;

        UINT32 index = Configuration.SPI_mod;

        
        AT91_SPI &spi = AT91::SPI(index);
        
        // make sure we didn't start one in the middle of an existing transaction
        /* if( spi.SPI_SR & AT91_SPI::SPI_SR_SPIENS ) 
        {
        lcd_printf("\fSPI Collision 1\r\n");
        hal_printf("\fSPI Collision 1\r\n");
        HARD_BREAKPOINT();

        return FALSE;
        }*/
        
        if(Configuration.SPI_mod == 0)
        {
            //Alterate GPIO pins to periphal pins
            CPU_GPIO_DisablePin(AT91_SPI0_SCLK, RESISTOR_DISABLED, 0, GPIO_ALT_MODE_1);
            CPU_GPIO_DisablePin(AT91_SPI0_MOSI, RESISTOR_DISABLED, 0, GPIO_ALT_MODE_1);
            CPU_GPIO_DisablePin(AT91_SPI0_MISO, RESISTOR_DISABLED, 0, GPIO_ALT_MODE_1);
//            if (Configuration.DeviceCS == AT91_SPI0_NSS)
//                CPU_GPIO_DisablePin(AT91_SPI0_NSS, RESISTOR_DISABLED, 0, GPIO_ALT_MODE_1);
            
        }
#if defined(PLATFORM_ARM_SAM9261_ANY)        
        else
        {
            //Alterate GPIO pins to periphal pins
            CPU_GPIO_DisablePin(AT91_SPI1_SCLK, RESISTOR_DISABLED, 0, GPIO_ALT_MODE_1);
            CPU_GPIO_DisablePin(AT91_SPI1_MOSI, RESISTOR_DISABLED, 0, GPIO_ALT_MODE_1);
            CPU_GPIO_DisablePin(AT91_SPI1_MISO, RESISTOR_DISABLED, 0, GPIO_ALT_MODE_1);

// we don't implement the NSS/CS function in th SPI core.
//            if (Configuration.DeviceCS == AT91_SPI1_NSS)
//                CPU_GPIO_DisablePin(AT91_SPI1_NSS, RESISTOR_DISABLED, 0, GPIO_ALT_MODE_1);
        }
#elif defined(PLATFORM_ARM_SAM7X_ANY) 
        else
        {         
BOOL CPU_SPI_Xaction_Start( const SPI_CONFIGURATION& Configuration )
{
    NATIVE_PROFILE_HAL_PROCESSOR_SPI();
    if (Configuration.SPI_mod >= STM32F4_SPI_MODS) return FALSE;
    
	// CS setup
    CPU_GPIO_EnableOutputPin( Configuration.DeviceCS, Configuration.CS_Active );
    if(Configuration.CS_Setup_uSecs)
    {
        HAL_Time_Sleep_MicroSeconds_InterruptEnabled( Configuration.CS_Setup_uSecs );
    }
	
	
	// I/O setup
    GPIO_PIN msk, miso, mosi;
    CPU_SPI_GetPins(Configuration.SPI_mod, msk, miso, mosi);
    UINT32 alternate = 0x252; // AF5 = SPI1/SPI2
    if (Configuration.SPI_mod == 2) alternate = 0x262; // AF6 = SPI3, speed = 2 (50MHz)
    CPU_GPIO_DisablePin( msk,  RESISTOR_DISABLED, 1, (GPIO_ALT_MODE)alternate);
    CPU_GPIO_DisablePin( miso, RESISTOR_DISABLED, 0, (GPIO_ALT_MODE)alternate);
    CPU_GPIO_DisablePin( mosi, RESISTOR_DISABLED, 1, (GPIO_ALT_MODE)alternate);
    
    
	
	
    switch (Configuration.SPI_mod) {
    case 0: RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; break; // enable SPI1 clock
    case 1: RCC->APB1ENR |= RCC_APB1ENR_SPI2EN; break; // enable SPI2 clock
    case 2: RCC->APB1ENR |= RCC_APB1ENR_SPI3EN; break; // enable SPI3 clock
    }
    
    ptr_SPI_TypeDef spi = g_STM32_Spi_Port[Configuration.SPI_mod];
    
    // set mode bits
    UINT32 cr1 = SPI_CR1_SSM | SPI_CR1_SSI | SPI_CR1_MSTR | SPI_CR1_SPE;
    if (Configuration.MD_16bits) cr1 |= SPI_CR1_DFF;
    if (Configuration.MSK_IDLE) cr1 |= SPI_CR1_CPOL | SPI_CR1_CPHA;
    if (!Configuration.MSK_SampleEdge) cr1 ^= SPI_CR1_CPHA; // toggle phase
    
    // set clock prescaler
    UINT32 clock = SYSTEM_APB2_CLOCK_HZ / 2000; // SPI1 on APB2
    if (Configuration.SPI_mod !=  0) clock = SYSTEM_APB1_CLOCK_HZ / 2000; // SPI2/3 on APB1
    
    if (clock > Configuration.Clock_RateKHz << 3) {
        clock >>= 4;
        cr1 |= SPI_CR1_BR_2;
    }
예제 #9
0
BOOL AT91_SPI_Driver::Initialize()
{
    NATIVE_PROFILE_HAL_PROCESSOR_SPI();

    // Power Management Controller
    AT91_PMC &pmc = AT91::PMC();


    // Start by disabling the modules, since it does not happen on reset
    for(int i = 0; i < AT91_SPI::c_MAX_SPI; i++)
    {
        if(g_AT91_SPI_Driver.m_initialized[i] == FALSE)
        {
            AT91_SPI &spi = AT91::SPI(i);

            spi.SPI_CR |= AT91_SPI::SPI_CR_DISABLE_SPI; //Disable SPI Module, don't care the other bit.

            g_AT91_SPI_Driver.m_initialized[i] = TRUE;
        } 
	

    }

    pmc.EnablePeriphClock(AT91C_ID_SPI0);

#if (AT91C_MAX_SPI == 2)
    pmc.EnablePeriphClock(AT91C_ID_SPI1);
#endif

    // set up the GPIOs, always set them in the right state, as some other peripheral could have stolen them

    // should not put the SPI pins to any state, as it is unknown what user has connected it to.
    // put pins as in input would be the safest state.
    // SPI 0
    CPU_GPIO_EnableInputPin(AT91_SPI0_SCLK, FALSE, NULL, GPIO_INT_NONE, RESISTOR_PULLUP);
    CPU_GPIO_EnableInputPin(AT91_SPI0_MOSI, FALSE, NULL, GPIO_INT_NONE, RESISTOR_PULLUP);
    CPU_GPIO_EnableInputPin(AT91_SPI0_MISO, FALSE, NULL, GPIO_INT_NONE, RESISTOR_PULLUP);
    
#if (AT91C_MAX_SPI == 2)
    // SPI 1 
    CPU_GPIO_EnableInputPin(AT91_SPI1_SCLK, FALSE, NULL, GPIO_INT_NONE, RESISTOR_PULLUP);
    CPU_GPIO_EnableInputPin(AT91_SPI1_MOSI, FALSE, NULL, GPIO_INT_NONE, RESISTOR_PULLUP);
    CPU_GPIO_EnableInputPin(AT91_SPI1_MISO, FALSE, NULL, GPIO_INT_NONE, RESISTOR_PULLUP);
#endif
    return TRUE;
}
예제 #10
0
BOOL AT91_SPI_Driver::nWrite16_nRead16(const SPI_CONFIGURATION &Configuration, UINT16 *Write16, INT32 WriteCount, UINT16 *Read16, INT32 ReadCount, INT32 ReadStartOffset)
{
    NATIVE_PROFILE_HAL_PROCESSOR_SPI();
    GLOBAL_LOCK(irq);
    
    SPI_DEBUG_PRINT(" spi write 16 \r\n");
    
    if(g_AT91_SPI_Driver.m_Enabled[Configuration.SPI_mod])
    {
        lcd_printf("\fSPI Xaction 1\r\n");
        hal_printf("\fSPI Xaction 1\r\n");
        HARD_BREAKPOINT();
        return FALSE;
    }

    if(Configuration.SPI_mod > AT91_SPI::c_MAX_SPI)
    {
        lcd_printf("\fSPI wrong mod\r\n");
        hal_printf("\fSPI wrong mod\r\n");
        HARD_BREAKPOINT();
        return FALSE;
    }

    if(!Xaction_Start(Configuration))
        return FALSE;
    {
        SPI_XACTION_16 Transaction;

        Transaction.Read16 = Read16;
        Transaction.ReadCount = ReadCount;
        Transaction.ReadStartOffset = ReadStartOffset;
        Transaction.Write16 = Write16;
        Transaction.WriteCount = WriteCount;
        Transaction.SPI_mod = Configuration.SPI_mod;
        Transaction.BusyPin = Configuration.BusyPin;

        if(!Xaction_nWrite16_nRead16(Transaction))
            return FALSE;
    }

    SPI_DEBUG_PRINT(" B4 xs 16 \r\n");

    return Xaction_Stop(Configuration);
}
BOOL AT91_SPI_Driver::nWrite8_nRead8(const SPI_CONFIGURATION &Configuration, UINT8 *Write8, INT32 WriteCount, UINT8 *Read8, INT32 ReadCount, INT32 ReadStartOffset)
{
    NATIVE_PROFILE_HAL_PROCESSOR_SPI();

   
    SPI_DEBUG_PRINT(" spi write 8 \r\n");
    if(g_AT91_SPI_Driver.m_Enabled[Configuration.SPI_mod])
    {
        lcd_printf("\fSPI Xaction 1\r\n");
        HARD_BREAKPOINT();
        return FALSE;
    }
    
    if(Configuration.SPI_mod > AT91_SPI::c_MAX_SPI)
    {
        lcd_printf("\fSPI wrong mod\r\n");
        HARD_BREAKPOINT();
        return FALSE;
    }
    
    if(!Xaction_Start(Configuration))
        return FALSE;

    
    {
        SPI_XACTION_8 Transaction;

        Transaction.Read8 = Read8;
        Transaction.ReadCount = ReadCount;
        Transaction.ReadStartOffset = ReadStartOffset;
        Transaction.Write8 = Write8;
        Transaction.WriteCount = WriteCount;
        Transaction.SPI_mod = Configuration.SPI_mod;
        Transaction.BusyPin = Configuration.BusyPin;

        if(!Xaction_nWrite8_nRead8(Transaction))
            return FALSE;
    }
    
    
    return Xaction_Stop(Configuration);
}
예제 #12
0
BOOL CPU_SPI_Xaction_Start( const SPI_CONFIGURATION& Configuration )
{
    NATIVE_PROFILE_HAL_PROCESSOR_SPI();
    if (Configuration.SPI_mod >= 3) return FALSE;
    
    SPI_TypeDef* spi = g_STM32_Spi[Configuration.SPI_mod];
    
    // set mode bits
    UINT32 cr1 = SPI_CR1_SSM | SPI_CR1_SSI | SPI_CR1_MSTR | SPI_CR1_SPE;
    if (Configuration.MD_16bits) cr1 |= SPI_CR1_DFF;
    if (Configuration.MSK_IDLE) cr1 |= SPI_CR1_CPOL | SPI_CR1_CPHA;
    if (!Configuration.MSK_SampleEdge) cr1 ^= SPI_CR1_CPHA; // toggle phase
    
    // set clock prescaler
    UINT32 clock = SYSTEM_APB2_CLOCK_HZ / 2000; // SPI1 on APB2
    if (Configuration.SPI_mod > 0) clock = SYSTEM_APB1_CLOCK_HZ / 2000; // SPI2/3 on APB1
    
    if (clock > Configuration.Clock_RateKHz << 3) {
        clock >>= 4;
        cr1 |= SPI_CR1_BR_2;
    }
예제 #13
0
void MC9328MXL_SPI_Driver::GetPins( UINT32 spi_mod, GPIO_PIN& msk, GPIO_PIN& miso, GPIO_PIN& mosi )
{
    NATIVE_PROFILE_HAL_PROCESSOR_SPI();

    switch (spi_mod)
    {
    case (MC9328MXL_SPI::c_SPI1):
        msk  = MC9328MXL_SPI::c_SPI1_SCLK;;
        miso = MC9328MXL_SPI::c_SPI1_MISO;
        mosi = MC9328MXL_SPI::c_SPI1_MOSI;

        break;
    case (MC9328MXL_SPI::c_SPI2):
        msk  = MC9328MXL_SPI::c_SPI2_SCLK;;
        miso = MC9328MXL_SPI::c_SPI2_MISO;
        mosi = MC9328MXL_SPI::c_SPI2_MOSI;

        break;
    default:
        break;

    }

}
예제 #14
0
BOOL MC9328MXL_SPI_Driver::Xaction_nWrite8_nRead8( SPI_XACTION_8& Transaction )
{
    NATIVE_PROFILE_HAL_PROCESSOR_SPI();
    UINT8 Data8;

    if(!g_MC9328MXL_SPI_Driver.m_Enabled[ Transaction.SPI_mod ])
    {
        lcd_printf("\fSPI Xaction OFF\r\n");
        ASSERT(FALSE);
        return FALSE;
    }

    MC9328MXL_SPI& SPI = MC9328MXL::SPI( Transaction.SPI_mod );

    UINT8* Write8          = Transaction.Write8;
    INT32  WriteCount      = Transaction.WriteCount;
    UINT8* Read8           = Transaction.Read8;
    INT32  ReadCount       = Transaction.ReadCount;
    INT32  ReadStartOffset = Transaction.ReadStartOffset;
    INT32  ReadTotal        = 0;

    // as master, we must always write something before reading or not
    if(WriteCount <= 0)                    {
        ASSERT(FALSE);
        return FALSE;
    }
    if(Write8 == NULL)                     {
        ASSERT(FALSE);
        return FALSE;
    }
    if((ReadCount > 0) && (Read8 == NULL)) {
        ASSERT(FALSE);
        return FALSE;
    }

    if(ReadCount)
    {
        ReadTotal = ReadCount + ReadStartOffset;    // we need to read as many bytes as the buffer is long, plus the offset at which we start
    }

    INT32 loopCnt= ReadTotal;

    // take the max of Read+offset or WrCnt
    if (loopCnt < WriteCount)
        loopCnt = WriteCount;

    // we will use WriteCount to move in the Write8 array
    // so we do no want to go past the end when we will check for
    // WriteCount to be bigger than zero
    WriteCount -= 1;

    // Start transmission
    while(loopCnt--)
    {
        SPI.TXDATAREG = Write8[0];
        SPI.CONTROLREG |= SPI.CONTROLREG_XCH;

        // wait while the transmit buffer is full and receive buffer is empty
        while(!SPI.TransmitBufferEmpty() || !SPI.ShiftBufferEmpty()|| SPI.ReceiveBufferEmpty());

        // reading clears the RBF bit and allows another transfer from the shift register
        Data8 = SPI.RXDATAREG;
        // repeat last write word for all subsequent reads

        if(WriteCount)
        {
            WriteCount--;
            Write8++;
        }

        // only save data once we have reached ReadCount-1 portion of words
        ReadTotal--;
        if((ReadTotal>=0) && (ReadTotal < ReadCount))
        {
            Read8[0] = Data8;
            Read8++;
        }

    }
    return TRUE;
}
예제 #15
0
BOOL MC9328MXL_SPI_Driver::Xaction_Stop( const SPI_CONFIGURATION& Configuration )
{
    NATIVE_PROFILE_HAL_PROCESSOR_SPI();
    if(g_MC9328MXL_SPI_Driver.m_Enabled[Configuration.SPI_mod])
    {
        UINT32 index = Configuration.SPI_mod;

        MC9328MXL_SPI & SPI = MC9328MXL::SPI(index);

        // we should have cleared the last TBF on the last RBF true setting
        // we should never bring CS inactive with the shifter busy
        ASSERT( SPI.TransmitBufferEmpty());
        ASSERT( SPI.ReceiveBufferEmpty ());
        ASSERT( SPI.ShiftBufferEmpty   ());

        if(Configuration.CS_Hold_uSecs)
        {
            HAL_Time_Sleep_MicroSeconds_InterruptEnabled( Configuration.CS_Hold_uSecs );
        }



        // avoid noise drawing excess power on a floating line by putting this in pulldown
#if defined(PLATFORM_ARM_MC9328MXS)
        CPU_GPIO_EnableInputPin( MC9328MXL_SPI::c_SPI1_MISO, FALSE, NULL, GPIO_INT_NONE, RESISTOR_PULLUP );
#else
        if (index == MC9328MXL_SPI::c_SPI1)
        {
            CPU_GPIO_EnableInputPin( MC9328MXL_SPI::c_SPI1_MISO, FALSE, NULL, GPIO_INT_NONE, RESISTOR_PULLUP );
        }
        else
        {
            CPU_GPIO_EnableInputPin( MC9328MXL_SPI::c_SPI2_MISO, FALSE, NULL, GPIO_INT_NONE, RESISTOR_PULLUP );
        }
#endif

        // next, bring the CS to the proper inactive state
        if((Configuration.DeviceCS != MC9328MXL_GPIO::c_Pin_None) && (Configuration.DeviceCS != MC9328MXL_SPI::c_SPI1_SS))
        {
            CPU_GPIO_SetPinState( Configuration.DeviceCS, !Configuration.CS_Active );
        }

        // make sure that we don't trigger the SS pin for LCD on the iMXS board, this may change if Freescale change their circuitry
        // can remove if not use on imxs platform
        // be safe, as LCD SPI access will use this function as well, set it back to Output
#if (HARDWARE_BOARD_TYPE >= HARDWARE_BOARD_i_MXS_DEMO_REV_V1_2)
        CPU_GPIO_EnableOutputPin( MC9328MXL_SPI::c_SPI1_SS, TRUE );

#endif

        // put pins in output low state when not in use to avoid noise since clock stop and reset will cause these to become inputs
#if defined(PLATFORM_ARM_MC9328MXS)
        CPU_GPIO_EnableOutputPin( MC9328MXL_SPI::c_SPI1_SCLK, FALSE );
        CPU_GPIO_EnableOutputPin( MC9328MXL_SPI::c_SPI1_MOSI, FALSE );
#else
        if (index == MC9328MXL_SPI::c_SPI1)
        {
            CPU_GPIO_EnableOutputPin( MC9328MXL_SPI::c_SPI1_SCLK, FALSE );
            CPU_GPIO_EnableOutputPin( MC9328MXL_SPI::c_SPI1_MOSI, FALSE );
        }
        else
        {
            CPU_GPIO_EnableOutputPin( MC9328MXL_SPI::c_SPI2_SCLK, FALSE );
            CPU_GPIO_EnableOutputPin( MC9328MXL_SPI::c_SPI2_MOSI, FALSE );
        }
#endif

        // off SPI module
        SPI.CONTROLREG &=  ~SPI.CONTROLREG_SPIEN;

        g_MC9328MXL_SPI_Driver.m_Enabled[Configuration.SPI_mod] = FALSE;
    }
    else
    {
        lcd_printf("\fSPI Collision 4\r\n");
        HARD_BREAKPOINT();

        return FALSE;
    }

    return TRUE;
}
예제 #16
0
BOOL MC9328MXL_SPI_Driver::Xaction_Start( const SPI_CONFIGURATION& Configuration )
{
    NATIVE_PROFILE_HAL_PROCESSOR_SPI();
    if(!g_MC9328MXL_SPI_Driver.m_Enabled[Configuration.SPI_mod])
    {
        g_MC9328MXL_SPI_Driver.m_Enabled[Configuration.SPI_mod] = TRUE;

        UINT32 index = Configuration.SPI_mod;

        MC9328MXL_SPI & SPI = MC9328MXL::SPI(index);

        // make sure we didn't start one in the middle of an existing transaction
        if( SPI.CONTROLREG & SPI.CONTROLREG_SPIEN )
        {
            lcd_printf("\fSPI Collision 1\r\n");
            hal_printf("\fSPI Collision 1\r\n");
            HARD_BREAKPOINT();

            return FALSE;
        }

        // first build the mode register
        SPI.CONTROLREG = MC9328MXL_SPI::ConfigurationToMode( Configuration );

        // LCD Controller needs to have Pulse mode enabled
#if (HARDWARE_BOARD_TYPE >= HARDWARE_BOARD_i_MXS_DEMO_REV_V1_2)
        if(Configuration.DeviceCS == MC9328MXL_SPI::c_SPI1_SS)
        {
            SPI.PERIODREG = 2;

            SPI.CONTROLREG |= MC9328MXL_SPI::CONTROLREG_SSCTL_PULSE;       // Pulse SS between bursts

            // set the SSPOL to active lo as it is force at the ConfigurationMOde to not trigger SS for other SPI operation
            SPI.CONTROLREG &= (~MC9328MXL_SPI::CONTROLREG_SSPOL_HIGH);       // Pulse SS between bursts
            CPU_GPIO_DisablePin( MC9328MXL_SPI::c_SPI1_SS,RESISTOR_DISABLED, 0, GPIO_ALT_PRIMARY);

        }
#endif


        SPI.CONTROLREG |= MC9328MXL_SPI::CONTROLREG_SPIEN;

#if (SPI_LOOP_BACK)
        // for spi testing
        SPI.TESTREG |= SPI.TESTREG_LBC;
#endif

        // everything should be clean and idle
        ASSERT( SPI.TransmitBufferEmpty());
        ASSERT( SPI.ReceiveBufferEmpty());
        ASSERT( SPI.ShiftBufferEmpty  ());

        // make sure not trigger the SS pin for the LCD when doing any SPI activity.
        // but we can have LCD SPI activity, if so, we want the SS be able to drive
#if (HARDWARE_BOARD_TYPE >= HARDWARE_BOARD_i_MXS_DEMO_REV_V1_2)
        if(Configuration.DeviceCS != MC9328MXL_SPI::c_SPI1_SS)
        {
            CPU_GPIO_EnableInputPin( MC9328MXL_SPI::c_SPI1_SS, FALSE, NULL, GPIO_INT_NONE, RESISTOR_PULLUP );
        }
#endif

#if defined(PLATFORM_ARM_MC9328MXS)
        // make sure that we don't trigger the SS pin for LCD
        CPU_GPIO_DisablePin( MC9328MXL_SPI::c_SPI1_SCLK, RESISTOR_DISABLED, 0, GPIO_ALT_PRIMARY);
        CPU_GPIO_DisablePin( MC9328MXL_SPI::c_SPI1_MOSI, RESISTOR_DISABLED, 0, GPIO_ALT_PRIMARY);
#else  // MC9328MXL
        if (index == MC9328MXL_SPI::c_SPI1)
        {
            // allow peripheral control of pins
            CPU_GPIO_DisablePin( MC9328MXL_SPI::c_SPI1_SCLK, RESISTOR_DISABLED, 0, GPIO_ALT_PRIMARY);
            CPU_GPIO_DisablePin( MC9328MXL_SPI::c_SPI1_MOSI, RESISTOR_DISABLED, 0, GPIO_ALT_PRIMARY);
        }
        else
        {
            // SPI2 need to set to Alternate function - AIN
            CPU_GPIO_DisablePin(MC9328MXL_SPI::c_SPI2_SCLK, RESISTOR_DISABLED, MC9328MXL_GPIO::DDIR__OUT, GPIO_ALT_MODE_1);
            CPU_GPIO_DisablePin(MC9328MXL_SPI::c_SPI2_MOSI, RESISTOR_DISABLED, MC9328MXL_GPIO::DDIR__OUT, GPIO_ALT_MODE_1);
        }
#endif

        // first set CS active as soon as clock and data pins are in proper initial state
        if((Configuration.DeviceCS != MC9328MXL_GPIO::c_Pin_None) && (Configuration.DeviceCS != MC9328MXL_SPI::c_SPI1_SS))
        {
            CPU_GPIO_EnableOutputPin( Configuration.DeviceCS, Configuration.CS_Active );
        }

#if defined(PLATFORM_ARM_MC9328MXS)
        CPU_GPIO_DisablePin( MC9328MXL_SPI::c_SPI1_MISO, RESISTOR_DISABLED, 0, GPIO_ALT_PRIMARY );
#else
        if (index == MC9328MXL_SPI::c_SPI1)
        {
            CPU_GPIO_DisablePin( MC9328MXL_SPI::c_SPI1_MISO, RESISTOR_DISABLED, 0, GPIO_ALT_PRIMARY );
        }
        else
        {
            // set AOUT mode for MISO for SPI 2
            CPU_GPIO_DisablePin(MC9328MXL_SPI::c_SPI2_MISO, RESISTOR_DISABLED,MC9328MXL_GPIO::DDIR__IN ,GPIO_ALT_MODE_4);
            MC9328MXL::SC().FMCR |= MC9328MXL_SC::FMCR__SPI2_RXD_SEL;
        }
#endif

        if(Configuration.CS_Setup_uSecs)
        {
            HAL_Time_Sleep_MicroSeconds_InterruptEnabled( Configuration.CS_Setup_uSecs );
        }
    }
    else
    {
        lcd_printf( "\fSPI Collision 3\r\n" );
        HARD_BREAKPOINT();

        return FALSE;
    }

    return TRUE;
}