##// END OF EJS Templates
Removed error on fat32 library, seems now to be able navigate among sectors in...
Removed error on fat32 library, seems now to be able navigate among sectors in both directions. Improved SDLCD drawing performances by almost 1000x.

File last commit:

r64:b702edc52366 dev_alexis
r68:104125d87b89 dev_alexis
Show More
spi.c
470 lines | 10.9 KiB | text/x-c | CLexer
/*------------------------------------------------------------------------------
-- This file is a part of the libuc, microcontroler library
-- Copyright (C) 2011, Alexis Jeandet
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-------------------------------------------------------------------------------
-- Author : Alexis Jeandet
-- Mail : alexis.jeandet@member.fsf.org
-------------------------------------------------------------------------------*/
#include <spi.h>
#include <stm32f4xx_rcc.h>
#include <stm32f4xx_gpio.h>
#include <gpio.h>
#define GPIOGETPORT(gpio) ((GPIO_TypeDef*)(((((uint32_t)gpio) & (uint32_t)0x0000FF00)*(uint32_t)4) + (uint32_t)GPIOA))
#define GPIOPORTNUM(gpio) (((uint32_t)(gpio) & (uint32_t)0x0000FF00)>>(uint32_t)8)
SPI_TypeDef* _spi_dev_table[3]={SPI1,SPI2,SPI3};
spi_t spiopen(int count)
{
#define _INIT_DEV(_RCC_) \
RCC_APB1PeriphClockCmd(_RCC_, ENABLE); \
RCC_APB1PeriphResetCmd(_RCC_, ENABLE); \
RCC_APB1PeriphResetCmd(_RCC_, DISABLE); \
RCC_APB1PeriphClockCmd(_RCC_, ENABLE);
switch(count)
{
case spi1:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, DISABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
return spi1;
break;
case spi2:
_INIT_DEV(RCC_APB1Periph_SPI2);
return spi2;
break;
case spi3:
_INIT_DEV(RCC_APB1Periph_SPI3);
return spi3;
break;
default:
break;
}
return -1;
}
spi_t spiopenandconfig(int count, uint32_t cfg, uint32_t speed, uint32_t MOSIpin, uint32_t MISOpin, uint32_t SCKpin, uint32_t SCSpin)
{
spi_t dev = spiopen(count);
if(dev!=-1)
{
spidisable(dev);
spisetpins(dev,MOSIpin, MISOpin, SCKpin, SCSpin);
spienable(dev);
spisetconfig(dev,cfg,speed);
}
return dev;
}
int spiclose(spi_t spidev)
{
if((spidev<3)&&(spidev>=0))
{
switch(spidev)
{
case spi1:
RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, ENABLE);
break;
case spi2:
RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2, ENABLE);
break;
case spi3:
RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI3, ENABLE);
break;
default:
return -1;
break;
}
return 1;
}
return -1;
}
int spisetpins(spi_t spidev,uint32_t MOSIpin,uint32_t MISOpin,uint32_t SCKpin,uint32_t SCSpin)
{
if((spidev<3)&&(spidev>=0))
{
SPI_TypeDef* _dev_ = _spi_dev_table[(int)spidev];
gpio_t MISO,MOSI,SCK,SCS;
uint8_t gpioAFspix = GPIO_AF_SPI1;
switch(spidev)
{
case spi1:
gpioAFspix = GPIO_AF_SPI1;
break;
case spi2:
gpioAFspix = GPIO_AF_SPI2;
break;
case spi3:
gpioAFspix = GPIO_AF_SPI3;
break;
default:
break;
}
if(MISOpin!=-1)
{
MISO = gpioopen(MISOpin);
MISO |= gpiohighspeed | gpioaf | gpiopushpulltype | gpionopulltype;
gpiosetconfig(&MISO);
GPIO_PinAFConfig(GPIOGETPORT(MISO), (uint8_t)(MISO & 0xF), gpioAFspix);
}
if(MOSIpin!=-1)
{
MOSI = gpioopen(MOSIpin);
MOSI |= gpiohighspeed | gpioaf | gpiopushpulltype | gpionopulltype;
gpiosetconfig(&MOSI);
GPIO_PinAFConfig(GPIOGETPORT(MOSI), (uint8_t)(MOSI & 0xF), gpioAFspix);
}
if(SCKpin!=-1)
{
SCK = gpioopen(SCKpin);
SCK |= gpiohighspeed | gpioaf | gpiopushpulltype | gpionopulltype;
gpiosetconfig(&SCK);
GPIO_PinAFConfig(GPIOGETPORT(SCK), (uint8_t)(SCK & 0xF), gpioAFspix);
}
if(SCSpin!=-1)
{
SCS = gpioopen(SCSpin);
SCS |= gpiohighspeed | gpioaf | gpiopushpulltype | gpionopulltype;
gpiosetconfig(&SCS);
GPIO_PinAFConfig(GPIOGETPORT(SCS), (uint8_t)(SCS & 0xF), gpioAFspix);
_dev_->CR2 |= (1<<2);
}
else
{
_dev_->CR2 &= ~(1<<2);
}
return 1;
}
return -1;
}
int spienable(spi_t spidev)
{
if((spidev<3)&&(spidev>=0))
{
SPI_TypeDef* _dev_ = _spi_dev_table[(int)spidev];
_dev_->CR1 |= (1<<6);
return 1;
}
return -1;
}
int spidisable(spi_t spidev)
{
if((spidev<3)&&(spidev>=0))
{
SPI_TypeDef* _dev_ = _spi_dev_table[(int)spidev];
_dev_->CR1 &= ~(1<<6);
return 1;
}
return -1;
}
int spisetconfig(spi_t spidev, uint32_t config, uint32_t speed)
{
if((spidev<3)&&(spidev>=0))
{
SPI_TypeDef* _dev_ = _spi_dev_table[(int)spidev];
_dev_->CR2 |= (1<<2);
_dev_->CR1 |= (1<<2);
spisetspeed(spidev,speed);
spisetdatabits(spidev,config & SPIBITSMASK);
spisetbitorder(spidev,config & SPIBITORDERMASK);
spisetclkinhlevel(spidev,config & SPICLKINHLVLMASK);
spisetclkphase(spidev,config & SPICLKPHASEMASK);
return 0;
}
return 1;
}
int spisetspeed(spi_t spidev, uint32_t speed)
{
if((spidev<3)&&(spidev>=0))
{
SPI_TypeDef* _dev_ = _spi_dev_table[(int)spidev];
uint32_t apbclock = 0x00;
RCC_ClocksTypeDef RCC_ClocksStatus;
RCC_GetClocksFreq(&RCC_ClocksStatus);
if (_dev_ == SPI1)
{
apbclock = RCC_ClocksStatus.PCLK2_Frequency;
}
else
{
apbclock = RCC_ClocksStatus.PCLK1_Frequency;
}
int32_t speederror = 0x7FFFFFFF; //max error
int32_t prev_speederror = 0x7FFFFFFF;
int32_t realspeed = 0;
unsigned char divider = 0;
do
{
divider ++;
prev_speederror = speederror;
realspeed = apbclock>>(divider);
speederror = realspeed - speed;
if(speederror<0)speederror=-speederror;
if(divider>8)break;
}while(speederror<prev_speederror);
speed = apbclock>>(divider-1);
divider-=2;
_dev_->CR1 &= 0xFFD7; // clear prescaler bits 3:5
_dev_->CR1 |= ((0x7 & divider)<<3);
return 1;
}
return -1;
}
uint32_t spigetspeed(spi_t spidev)
{
if((spidev<3)&&(spidev>=0))
{
SPI_TypeDef* _dev_ = _spi_dev_table[(int)spidev];
uint32_t apbclock = 0x00;
RCC_ClocksTypeDef RCC_ClocksStatus;
RCC_GetClocksFreq(&RCC_ClocksStatus);
if (_dev_ == SPI1)
{
apbclock = RCC_ClocksStatus.PCLK2_Frequency;
}
else
{
apbclock = RCC_ClocksStatus.PCLK1_Frequency;
}
int BR= (_dev_->CR1>>3)&0x7;
return apbclock>>(BR+1);
}
return -1;
}
int spisetdatabits(spi_t spidev,spibits_t bitscnt)
{
if((spidev<3)&&(spidev>=0))
{
SPI_TypeDef* _dev_ = _spi_dev_table[(int)spidev];
int result = 0;
switch(bitscnt)
{
case spi8bits:
_dev_->CR1 &= ~(1<<11);
result = 1;
break;
case spi16bits:
_dev_->CR1 |= (1<<11);
result = 1;
break;
default:
result =-1;
break;
}
return result;
}
return -1;
}
int spisetbitorder(spi_t spidev,spibitorder_t order)
{
if((spidev<3)&&(spidev>=0))
{
SPI_TypeDef* _dev_ = _spi_dev_table[(int)spidev];
if(order==spimsbfirst)
{
_dev_->CR1 &= ~(1<<7);
return 1;
}
else
{
if(order==spilsbfirst)
{
_dev_->CR1 |= (1<<7);
return 1;
}
else return -1;
}
}
return -1;
}
int spisetclkinhlevel(spi_t spidev,spiclkinhlvl_t level)
{
if((spidev<3)&&(spidev>=0))
{
SPI_TypeDef* _dev_ = _spi_dev_table[(int)spidev];
if(level==spiclkinhlow)
{
_dev_->CR1 &= ~(1<<1);
return 1;
}
else
{
if(level==spiclkinhhigh)
{
_dev_->CR1 |= (1<<1);
return 1;
}
else return -1;
}
}
return -1;
}
int spisetclkphase(spi_t spidev,spiclkphase_t phase)
{
if((spidev<3)&&(spidev>=0))
{
SPI_TypeDef* _dev_ = _spi_dev_table[(int)spidev];
if(phase==spiclkfirstedge)
{
_dev_->CR1 &= ~1;
return 1;
}
else
{
if(phase==spiclksecondedge)
{
_dev_->CR1 |= 1;
return 1;
}
else return -1;
}
}
return -1;
}
int spiputw(spi_t spidev,uint16_t data)
{
if((spidev<3)&&(spidev>=0))
{
SPI_TypeDef* _dev_ = _spi_dev_table[(int)spidev];
while(((_dev_->SR & (1<<1)) == 0) );
_dev_->DR = data;
while(((_dev_->SR & (1<<0)) == 0) );
return _dev_->DR;
}
return -1;
}
uint16_t spigetw(spi_t spidev)
{
if((spidev<3)&&(spidev>=0))
{
SPI_TypeDef* _dev_ = _spi_dev_table[(int)spidev];
while(((_dev_->SR & (1<<1)) == 0) );
_dev_->DR = 0xFFFF;
while(((_dev_->SR & (1<<0)) == 0) );
return _dev_->DR;
}
return -1;
}
int spiputs(spi_t spidev,char* s)
{
while (*s) spiputw(spidev,*s++);
return 1;
}
int spigets(spi_t spidev,char* s)
{
do
{
(*s) = spigetw(spidev);
}
while(*s++);
return 1;
}
int spiputnw(spi_t spidev,uint16_t* w,int n)
{
while(n!=0)
{
spiputw(spidev,*w++);
n--;
}
return 1;
}
int spigetnw(spi_t spidev,uint16_t* w,int n)
{
while(n!=0)
{
*w++=spigetw(spidev);
n--;
}
return 1;
}
int spiputnc(spi_t spidev,char* c,int n)
{
while(n!=0)
{
spiputw(spidev,*c++);
n--;
}
return 1;
}
int spigetnc(spi_t spidev,char* c,int n)
{
while(n!=0)
{
*c++=spigetw(spidev);
n--;
}
return 1;
}
int spiavailiabledata(spi_t spidev)
{
return 0;
}
int spitransactionfinished(spi_t spidev)
{
SPI_TypeDef* _dev_ = _spi_dev_table[(int)spidev];
if((spidev<3)&&(spidev>=0))
{
if((_dev_->SR & (1<<7)) == (1<<7))return 1;
}
return 0;
}