/* GECKO3COM
|
/* GECKO3COM
|
*
|
*
|
* Copyright (C) 2008 by
|
* Copyright (C) 2008 by
|
* ___ ___ _ _
|
* ___ ___ _ _
|
* ( _`\ ( __)( ) ( )
|
* ( _`\ ( __)( ) ( )
|
* | (_) )| ( | |_| | Berne University of Applied Sciences
|
* | (_) )| ( | |_| | Berne University of Applied Sciences
|
* | _ <'| _) | _ | School of Engineering and
|
* | _ <'| _) | _ | School of Engineering and
|
* | (_) )| | | | | | Information Technology
|
* | (_) )| | | | | | Information Technology
|
* (____/'(_) (_) (_)
|
* (____/'(_) (_) (_)
|
*
|
*
|
*
|
*
|
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
* (at your option) any later version.
|
* (at your option) any later version.
|
*
|
*
|
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
*/
|
*/
|
/************************************************************/
|
/************************************************************/
|
/** \file spi_flash.c
|
/** \file spi_flash.c
|
*************************************************************
|
*************************************************************
|
* \author Christoph Zimmermann
|
* \author Christoph Zimmermann
|
* \date Date of creation: 17.09.2007
|
* \date Date of creation: 17.09.2007
|
* \brief C code for the spi-flash Library
|
* \brief C code for the spi-flash Library
|
*
|
*
|
* \details Library to access the SPI Flash devices from ST
|
* \details Library to access the SPI Flash devices from ST
|
* Microelectronics (now Numonyx) or Spansion.
|
* Microelectronics (now Numonyx) or Spansion.
|
* Supported densities:
|
* Supported densities:
|
* 8, 16, 32 Mbit
|
* 8, 16, 32 Mbit
|
*
|
*
|
* \date 17.09.2007 first version, based on the m25p16.h header file
|
* \date 17.09.2007 first version, based on the m25p16.h header file
|
* \date 24. june 2009 code size optimization for the GECKO3COM firmware
|
* \date 24. june 2009 code size optimization for the GECKO3COM firmware
|
*
|
*
|
*/
|
*/
|
#include "spi_flash.h"
|
#include "spi_flash.h"
|
#include "spi.h"
|
#include "spi.h"
|
#include "debugprint.h"
|
#include "debugprint.h"
|
#include "stdint.h"
|
#include "stdint.h"
|
|
|
|
|
SPI_flash xdata flash_dr;
|
SPI_flash xdata flash_dr;
|
|
|
|
|
/** \brief Internal: Helper function to count the number of active (1) bits in a byte */
|
/** \brief Internal: Helper function to count the number of active (1) bits in a byte */
|
static unsigned char
|
static unsigned char
|
count_bits8 (unsigned char v)
|
count_bits8 (unsigned char v)
|
{
|
{
|
unsigned char count = 0;
|
unsigned char count = 0;
|
if (v & (1 << 0)) count++;
|
if (v & (1 << 0)) count++;
|
if (v & (1 << 1)) count++;
|
if (v & (1 << 1)) count++;
|
if (v & (1 << 2)) count++;
|
if (v & (1 << 2)) count++;
|
if (v & (1 << 3)) count++;
|
if (v & (1 << 3)) count++;
|
if (v & (1 << 4)) count++;
|
if (v & (1 << 4)) count++;
|
if (v & (1 << 5)) count++;
|
if (v & (1 << 5)) count++;
|
if (v & (1 << 6)) count++;
|
if (v & (1 << 6)) count++;
|
if (v & (1 << 7)) count++;
|
if (v & (1 << 7)) count++;
|
return count;
|
return count;
|
}
|
}
|
|
|
|
|
static void
|
static void
|
setup_enables (unsigned char enables)
|
setup_enables (unsigned char enables)
|
{
|
{
|
// Software enables are active high.
|
// Software enables are active high.
|
// Hardware enables are active low.
|
// Hardware enables are active low.
|
|
|
if(count_bits8(enables) > 1) {
|
if(count_bits8(enables) > 1) {
|
//print_error("en\n");
|
//print_error("en\n");
|
return;
|
return;
|
}
|
}
|
else {
|
else {
|
bitSPI_CLK = 0; //make shure spi_clk is low before we activate a device
|
bitSPI_CLK = 0; //make shure spi_clk is low before we activate a device
|
SPI_OE |= bmSPI_MASK; //activate spi bus
|
SPI_OE |= bmSPI_OE_MASK; //activate spi bus
|
enables &= bmSPI_CS_MASK;
|
enables &= bmSPI_CS_MASK;
|
SPI_CS_PORT |= bmSPI_CS_MASK; //disable all chipselect signals
|
SPI_CS_PORT |= bmSPI_CS_MASK; //disable all chipselect signals
|
SPI_CS_PORT &= ~enables;
|
SPI_CS_PORT &= ~enables;
|
//SPI_CS_OE |= enables;
|
SPI_CS_OE |= enables;
|
SPI_CS_OE |= bmSPI_CS_MASK;
|
SPI_CS_OE |= bmSPI_CS_MASK;
|
}
|
}
|
}
|
}
|
|
|
|
// setup_enables (0); SPI_CS_PORT |= bmSPI_CS_MASK; \ \
|
/** disables all SPI devices and sets the SPI and SPI CS signals to tri-state */
|
/** disables all SPI devices and sets the SPI and SPI CS signals to tri-state */
|
#define disable_all() { \
|
#define disable_all() { \
|
setup_enables (0); \
|
setup_enables (0); \
|
} /* SPI_OE &= ~bmSPI_MASK; \
|
SPI_CS_OE &= ~bmSPI_CS_MASK; \
|
SPI_CS_OE &= ~bmSPI_CS_MASK; \
|
SPI_OE &= ~bmSPI_OE_MASK; \
|
} */
|
}
|
|
|
|
|
/** \brief Internal: Writes one byte to the SPI bus
|
/** \brief Internal: Writes one byte to the SPI bus
|
*
|
*
|
* \param[in] data to write to the bus
|
* \param[in] data to write to the bus
|
*/
|
*/
|
static void
|
static void
|
write_byte_msb (unsigned char v);
|
write_byte_msb (unsigned char v);
|
|
|
|
|
/** \brief Internal: Writes a block of data to the SPI bus
|
/** \brief Internal: Writes a block of data to the SPI bus
|
*
|
*
|
* \param[in] pointer to a buffer to read the data from
|
* \param[in] pointer to a buffer to read the data from
|
* \param[in] length of the data to read
|
* \param[in] length of the data to read
|
*/
|
*/
|
static void
|
static void
|
write_bytes_msb (const xdata unsigned char *buf, unsigned char len);
|
write_bytes_msb (const xdata unsigned char *buf, unsigned char len);
|
|
|
|
|
/** \brief Internal: Reads a block of data from the SPI bus
|
/** \brief Internal: Reads a block of data from the SPI bus
|
*
|
*
|
* \param[in] pointer to a buffer to write the data to
|
* \param[in] pointer to a buffer to write the data to
|
* \param[in] length of the data to read
|
* \param[in] length of the data to read
|
*/
|
*/
|
static void
|
static void
|
read_bytes_msb (xdata unsigned char *buf, unsigned char len);
|
read_bytes_msb (xdata unsigned char *buf, unsigned char len);
|
|
|
|
|
/** \brief Internal: Writes a block of data in reversed order to the SPI bus
|
/** \brief Internal: Writes a block of data in reversed order to the SPI bus
|
*
|
*
|
* \param[in] pointer to a buffer to read the data from
|
* \param[in] pointer to a buffer to read the data from
|
* \param[in] length of the data to read
|
* \param[in] length of the data to read
|
*/
|
*/
|
static void
|
static void
|
write_bytes_msb_reversed (const xdata unsigned char *buf, unsigned char len);
|
write_bytes_msb_reversed (const xdata unsigned char *buf, unsigned char len);
|
|
|
|
|
/** \brief Checks if the SPI flash is busy */
|
/** \brief Checks if the SPI flash is busy */
|
int8_t spiflash_is_busy(xdata SPI_flash *flashPtr) {
|
int8_t spiflash_is_busy(xdata SPI_flash *flashPtr) {
|
xdata uint8_t buffer[2];
|
xdata uint8_t buffer[2];
|
|
|
if(flashPtr->isBusy) {
|
if(flashPtr->isBusy) {
|
//ask flash if still busy;
|
//ask flash if still busy;
|
setup_enables(bmSPI_CS_FLASH);
|
setup_enables(bmSPI_CS_FLASH);
|
|
|
write_byte_msb(RDSR);
|
write_byte_msb(RDSR);
|
read_bytes_msb(buffer, 2);
|
read_bytes_msb(buffer, 2);
|
|
|
disable_all();
|
disable_all();
|
|
|
if((buffer[1] & 1) == 1) {
|
if((buffer[1] & 1) == 1) {
|
return 1;
|
return 1;
|
}
|
}
|
else {
|
else {
|
flashPtr->isBusy = 0;
|
flashPtr->isBusy = 0;
|
}
|
}
|
}
|
}
|
|
|
return 0;
|
return 0;
|
}
|
}
|
|
|
|
|
/** \brief Initalizes the values in the SPI_flash struct after reading
|
/** \brief Initalizes the values in the SPI_flash struct after reading
|
* the device ID */
|
* the device ID */
|
int8_t init_spiflash(xdata SPI_flash *flashPtr) {
|
int8_t init_spiflash(xdata SPI_flash *flashPtr) {
|
|
|
uint8_t xdata flashID[3];
|
uint8_t xdata flashID[3];
|
uint8_t *idPtr = flashID;
|
uint8_t *idPtr = flashID;
|
int8_t xdata memsize;
|
int8_t xdata memsize;
|
uint32_t xdata maxAdress;
|
uint32_t xdata maxAdress;
|
uint32_t xdata capacity;
|
uint32_t xdata capacity;
|
uint16_t xdata pages;
|
uint16_t xdata pages;
|
uint8_t xdata sectors;
|
uint8_t xdata sectors;
|
|
|
|
|
/* init SPI */
|
/* init SPI */
|
disable_all (); /* disable all devs */
|
disable_all (); /* disable all devs */
|
bitSPI_MOSI = 0; /* idle state has CLK = 0 */
|
bitSPI_MOSI = 0; /* idle state has CLK = 0 */
|
|
|
ptrCheck(flashPtr);
|
ptrCheck(flashPtr);
|
|
|
setup_enables(bmSPI_CS_FLASH);
|
setup_enables(bmSPI_CS_FLASH);
|
write_byte_msb(RDID);
|
write_byte_msb(RDID);
|
read_bytes_msb (flashID, 3);
|
read_bytes_msb (flashID, 3);
|
disable_all();
|
disable_all();
|
|
|
if(*idPtr == MANUFACTURER_STM || *idPtr == MANUFACTURER_SPA) {
|
if(*idPtr == MANUFACTURER_STM || *idPtr == MANUFACTURER_SPA) {
|
idPtr++;
|
idPtr++;
|
if(*idPtr == MEMTYPE_STM) {
|
if(*idPtr == MEMTYPE_STM) {
|
memsize = 0;
|
memsize = 0;
|
}
|
}
|
else if(*idPtr == MEMTYPE_SPA) {
|
else if(*idPtr == MEMTYPE_SPA) {
|
memsize = 1;
|
memsize = 1;
|
}
|
}
|
else {
|
else {
|
return UNSUPPORTED_TYPE;
|
return UNSUPPORTED_TYPE;
|
}
|
}
|
|
|
idPtr++;
|
idPtr++;
|
memsize += *idPtr;
|
memsize += *idPtr;
|
|
|
|
|
switch(memsize) {
|
switch(memsize) {
|
case MEMCAPACITY_32MBIT_STM :
|
case MEMCAPACITY_32MBIT_STM :
|
maxAdress = MAXADRESS_32MBIT;
|
maxAdress = MAXADRESS_32MBIT;
|
capacity = FLASH_SIZE_32MBIT;
|
capacity = FLASH_SIZE_32MBIT;
|
pages = FLASH_PAGE_COUNT_32MBIT;
|
pages = FLASH_PAGE_COUNT_32MBIT;
|
sectors = FLASH_SECTOR_COUNT_32MBIT;
|
sectors = FLASH_SECTOR_COUNT_32MBIT;
|
break;
|
break;
|
case MEMCAPACITY_16MBIT_STM :
|
case MEMCAPACITY_16MBIT_STM :
|
maxAdress = MAXADRESS_16MBIT;
|
maxAdress = MAXADRESS_16MBIT;
|
capacity = FLASH_SIZE_16MBIT;
|
capacity = FLASH_SIZE_16MBIT;
|
pages = FLASH_PAGE_COUNT_16MBIT;
|
pages = FLASH_PAGE_COUNT_16MBIT;
|
sectors = FLASH_SECTOR_COUNT_16MBIT;
|
sectors = FLASH_SECTOR_COUNT_16MBIT;
|
break;
|
break;
|
case MEMCAPACITY_8MBIT_STM :
|
case MEMCAPACITY_8MBIT_STM :
|
maxAdress = MAXADRESS_8MBIT;
|
maxAdress = MAXADRESS_8MBIT;
|
capacity = FLASH_SIZE_8MBIT;
|
capacity = FLASH_SIZE_8MBIT;
|
pages = FLASH_PAGE_COUNT_8MBIT;
|
pages = FLASH_PAGE_COUNT_8MBIT;
|
sectors = FLASH_SECTOR_COUNT_8MBIT;
|
sectors = FLASH_SECTOR_COUNT_8MBIT;
|
break;
|
break;
|
default :
|
default :
|
return UNSUPPORTED_TYPE;
|
return UNSUPPORTED_TYPE;
|
}
|
}
|
|
|
flashPtr->maxAdress = maxAdress;
|
flashPtr->maxAdress = maxAdress;
|
flashPtr->capacity = capacity;
|
flashPtr->capacity = capacity;
|
flashPtr->pages = pages;
|
flashPtr->pages = pages;
|
flashPtr->sectors = sectors;
|
flashPtr->sectors = sectors;
|
|
|
return GOOD;
|
return GOOD;
|
}
|
}
|
else {
|
else {
|
return UNSUPPORTED_TYPE;
|
return UNSUPPORTED_TYPE;
|
/* debug stuff: */
|
/* debug stuff: */
|
//return *idPtr;
|
//return *idPtr;
|
}
|
}
|
}
|
}
|
|
|
|
|
/** \brief Reads data from the SPI flash */
|
/** \brief Reads data from the SPI flash */
|
int8_t spiflash_read(xdata SPI_flash *flashPtr, xdata uint32_t *adress, xdata uint8_t *buffer, const uint16_t length) {
|
int8_t spiflash_read(xdata SPI_flash *flashPtr, xdata uint32_t *adress, xdata uint8_t *buffer, const uint16_t length) {
|
|
|
//adrCheck(flashPtr, adress, length);
|
//adrCheck(flashPtr, adress, length);
|
|
|
while(spiflash_is_busy(flashPtr));
|
while(spiflash_is_busy(flashPtr));
|
|
|
//print_info("r\n");
|
//print_info("r\n");
|
|
|
/* we do a bit dirty programming here:
|
/* we do a bit dirty programming here:
|
* the adress of the device is only 24bit long, so we misuse the upper 8bits
|
* the adress of the device is only 24bit long, so we misuse the upper 8bits
|
* to send the read command to the spi flash.
|
* to send the read command to the spi flash.
|
* this avoids more complicated constructs. */
|
* this avoids more complicated constructs. */
|
*adress &= 0x00FFFFFF;
|
*adress &= 0x00FFFFFF;
|
*adress |= 0x03000000; //set the upper 8bit to the READ command
|
*adress |= 0x03000000; //set the upper 8bit to the READ command
|
|
|
/*printf_tiny("ad: %x,",((uint8_t*)adress)[2]);
|
/*printf_tiny("ad: %x,",((uint8_t*)adress)[2]);
|
printf_tiny("%x,",((uint8_t*)adress)[1]);
|
printf_tiny("%x,",((uint8_t*)adress)[1]);
|
printf_tiny("%x\n",((uint8_t*)adress)[0]);
|
printf_tiny("%x\n",((uint8_t*)adress)[0]);
|
*/
|
*/
|
|
|
setup_enables(bmSPI_CS_FLASH);
|
setup_enables(bmSPI_CS_FLASH);
|
|
|
write_bytes_msb_reversed((uint8_t*)adress, 4);
|
write_bytes_msb_reversed((uint8_t*)adress, 4);
|
if (length != 0) {
|
if (length != 0) {
|
read_bytes_msb (buffer, length);
|
read_bytes_msb (buffer, length);
|
}
|
}
|
|
|
disable_all();
|
disable_all();
|
|
|
return 1;
|
return 1;
|
}
|
}
|
|
|
/** \brief deletes one sector (64 kbyte) of the SPI flash */
|
/** \brief deletes one sector (64 kbyte) of the SPI flash */
|
int8_t spiflash_erase(xdata SPI_flash *flashPtr, xdata uint32_t *adress) {
|
int8_t spiflash_erase(xdata SPI_flash *flashPtr, xdata uint32_t *adress) {
|
while(spiflash_is_busy(flashPtr));
|
while(spiflash_is_busy(flashPtr));
|
|
|
setup_enables(bmSPI_CS_FLASH);
|
setup_enables(bmSPI_CS_FLASH);
|
write_byte_msb(WREN);
|
write_byte_msb(WREN);
|
disable_all();
|
disable_all();
|
|
|
/* we do a bit dirty programming here:
|
/* we do a bit dirty programming here:
|
* the adress of the device is only 24bit long, so we misuse the upper 8bits
|
* the adress of the device is only 24bit long, so we misuse the upper 8bits
|
* to send the read command to the spi flash.
|
* to send the read command to the spi flash.
|
* this avoids more complicated constructs. */
|
* this avoids more complicated constructs. */
|
*adress &= 0x00FFFFFF;
|
*adress &= 0x00FFFFFF;
|
*adress |= 0xD8000000; //set the upper 8bit to the SE (sector erase) command
|
*adress |= 0xD8000000; //set the upper 8bit to the SE (sector erase) command
|
|
|
//print_info("e\n");
|
//print_info("e\n");
|
|
|
setup_enables(bmSPI_CS_FLASH);
|
setup_enables(bmSPI_CS_FLASH);
|
write_bytes_msb_reversed((uint8_t*)adress, 4);
|
write_bytes_msb_reversed((uint8_t*)adress, 4);
|
disable_all();
|
disable_all();
|
|
|
flashPtr->isBusy = 1;
|
flashPtr->isBusy = 1;
|
|
|
return 1;
|
return 1;
|
}
|
}
|
|
|
|
|
/** \brief deletes the whole SPI flash */
|
/** \brief deletes the whole SPI flash */
|
int8_t spiflash_erase_bulk(xdata SPI_flash *flashPtr) {
|
int8_t spiflash_erase_bulk(xdata SPI_flash *flashPtr) {
|
while(spiflash_is_busy(flashPtr));
|
while(spiflash_is_busy(flashPtr));
|
setup_enables(bmSPI_CS_FLASH);
|
setup_enables(bmSPI_CS_FLASH);
|
write_byte_msb(WREN);
|
write_byte_msb(WREN);
|
disable_all();
|
disable_all();
|
|
|
setup_enables(bmSPI_CS_FLASH);
|
setup_enables(bmSPI_CS_FLASH);
|
write_byte_msb(BE);
|
write_byte_msb(BE);
|
disable_all();
|
disable_all();
|
|
|
flashPtr->isBusy = 1;
|
flashPtr->isBusy = 1;
|
|
|
return 1;
|
return 1;
|
}
|
}
|
|
|
|
|
/** \brief Writes data to the SPI flash */
|
/** \brief Writes data to the SPI flash */
|
int8_t spiflash_write(xdata SPI_flash *flashPtr, xdata uint32_t *adress, \
|
int8_t spiflash_write(xdata SPI_flash *flashPtr, xdata uint32_t *adress, \
|
xdata uint8_t *buffer, uint16_t length) {
|
xdata uint8_t *buffer, uint16_t length) {
|
|
|
xdata uint16_t writeableBytes;
|
xdata uint16_t writeableBytes;
|
|
|
while(length > 0) {
|
while(length > 0) {
|
|
|
while(spiflash_is_busy(flashPtr));
|
while(spiflash_is_busy(flashPtr));
|
|
|
setup_enables(bmSPI_CS_FLASH);
|
setup_enables(bmSPI_CS_FLASH);
|
write_byte_msb(WREN);
|
write_byte_msb(WREN);
|
disable_all();
|
disable_all();
|
|
|
writeableBytes = (uint16_t)(pageEnd(*adress)-*adress);
|
writeableBytes = (uint16_t)(pageEnd(*adress)-*adress);
|
writeableBytes ++;
|
writeableBytes ++;
|
|
|
if(length > writeableBytes) {
|
if(length > writeableBytes) {
|
length -= writeableBytes;
|
length -= writeableBytes;
|
}
|
}
|
else {
|
else {
|
writeableBytes = length;
|
writeableBytes = length;
|
length = 0;
|
length = 0;
|
}
|
}
|
|
|
//print_info("w\n");
|
//print_info("w\n");
|
//printf_tiny("%d\n",writeableBytes);
|
//printf_tiny("%d\n",writeableBytes);
|
|
|
/* we do a bit dirty programming here:
|
/* we do a bit dirty programming here:
|
* the adress of the device is only 24bit long, so we misuse the upper 8bits
|
* the adress of the device is only 24bit long, so we misuse the upper 8bits
|
* to send the read command to the spi flash.
|
* to send the read command to the spi flash.
|
* this avoids more complicated constructs. */
|
* this avoids more complicated constructs. */
|
*adress &= 0x00FFFFFF;
|
*adress &= 0x00FFFFFF;
|
*adress |= 0x02000000; //set the upper 8bit to the PP (page programm) command
|
*adress |= 0x02000000; //set the upper 8bit to the PP (page programm) command
|
|
|
/*printf_tiny("ad: %x,",((uint8_t*)adress)[3]);
|
/*printf_tiny("ad: %x,",((uint8_t*)adress)[3]);
|
printf_tiny("%x,",((uint8_t*)adress)[2]);
|
printf_tiny("%x,",((uint8_t*)adress)[2]);
|
printf_tiny("%x,",((uint8_t*)adress)[1]);
|
printf_tiny("%x,",((uint8_t*)adress)[1]);
|
printf_tiny("%x\n",((uint8_t*)adress)[0]);
|
printf_tiny("%x\n",((uint8_t*)adress)[0]);
|
*/
|
*/
|
setup_enables(bmSPI_CS_FLASH);
|
setup_enables(bmSPI_CS_FLASH);
|
write_bytes_msb_reversed((uint8_t*)adress, 4); //send the adress
|
write_bytes_msb_reversed((uint8_t*)adress, 4); //send the adress
|
|
|
/* the write_bytes_msb function can loop maximum 255 times, but a page is 256 long... */
|
/* the write_bytes_msb function can loop maximum 255 times, but a page is 256 long... */
|
write_byte_msb(buffer[0]);
|
write_byte_msb(buffer[0]);
|
buffer++;
|
buffer++;
|
write_bytes_msb(buffer, writeableBytes-1); //...thats why we split this to two writes
|
write_bytes_msb(buffer, writeableBytes-1); //...thats why we split this to two writes
|
disable_all();
|
disable_all();
|
|
|
*adress += writeableBytes;
|
*adress += writeableBytes;
|
buffer += writeableBytes;
|
buffer += writeableBytes;
|
buffer--; //adjust it because we incremented it once during the write
|
buffer--; //adjust it because we incremented it once during the write
|
|
|
flashPtr->isBusy = 1;
|
flashPtr->isBusy = 1;
|
}
|
}
|
|
|
return 1;
|
return 1;
|
}
|
}
|
|
|
/* ----------------------------------------------------------------
|
/* ----------------------------------------------------------------
|
* Internal functions
|
* Internal functions
|
*/
|
*/
|
static void
|
static void
|
write_byte_msb (unsigned char v)
|
write_byte_msb (unsigned char v)
|
{
|
{
|
//printf_tiny("0x%x",v);
|
//printf_tiny("0x%x",v);
|
v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit)
|
v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit)
|
bitSPI_MOSI = v & 0x1;
|
bitSPI_MOSI = v & 0x1;
|
bitSPI_CLK = 1;
|
bitSPI_CLK = 1;
|
bitSPI_CLK = 0;
|
bitSPI_CLK = 0;
|
|
|
v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit)
|
v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit)
|
bitSPI_MOSI = v & 0x1;
|
bitSPI_MOSI = v & 0x1;
|
bitSPI_CLK = 1;
|
bitSPI_CLK = 1;
|
bitSPI_CLK = 0;
|
bitSPI_CLK = 0;
|
|
|
v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit)
|
v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit)
|
bitSPI_MOSI = v & 0x1;
|
bitSPI_MOSI = v & 0x1;
|
bitSPI_CLK = 1;
|
bitSPI_CLK = 1;
|
bitSPI_CLK = 0;
|
bitSPI_CLK = 0;
|
|
|
v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit)
|
v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit)
|
bitSPI_MOSI = v & 0x1;
|
bitSPI_MOSI = v & 0x1;
|
bitSPI_CLK = 1;
|
bitSPI_CLK = 1;
|
bitSPI_CLK = 0;
|
bitSPI_CLK = 0;
|
|
|
v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit)
|
v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit)
|
bitSPI_MOSI = v & 0x1;
|
bitSPI_MOSI = v & 0x1;
|
bitSPI_CLK = 1;
|
bitSPI_CLK = 1;
|
bitSPI_CLK = 0;
|
bitSPI_CLK = 0;
|
|
|
v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit)
|
v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit)
|
bitSPI_MOSI = v & 0x1;
|
bitSPI_MOSI = v & 0x1;
|
bitSPI_CLK = 1;
|
bitSPI_CLK = 1;
|
bitSPI_CLK = 0;
|
bitSPI_CLK = 0;
|
|
|
v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit)
|
v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit)
|
bitSPI_MOSI = v & 0x1;
|
bitSPI_MOSI = v & 0x1;
|
bitSPI_CLK = 1;
|
bitSPI_CLK = 1;
|
bitSPI_CLK = 0;
|
bitSPI_CLK = 0;
|
|
|
v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit)
|
v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit)
|
bitSPI_MOSI = v & 0x1;
|
bitSPI_MOSI = v & 0x1;
|
bitSPI_CLK = 1;
|
bitSPI_CLK = 1;
|
bitSPI_CLK = 0;
|
bitSPI_CLK = 0;
|
}
|
}
|
|
|
static void
|
static void
|
write_bytes_msb (const xdata unsigned char *buf, unsigned char len)
|
write_bytes_msb (const xdata unsigned char *buf, unsigned char len)
|
{
|
{
|
while (len-- != 0){
|
while (len-- != 0){
|
//printf_tiny("0x%x, ",*buf);
|
//printf_tiny("0x%x, ",*buf);
|
write_byte_msb (*buf++);
|
write_byte_msb (*buf++);
|
}
|
}
|
}
|
}
|
|
|
static void
|
static void
|
write_bytes_msb_reversed (const xdata unsigned char *buf, unsigned char len)
|
write_bytes_msb_reversed (const xdata unsigned char *buf, unsigned char len)
|
{
|
{
|
while (len-- != 0){
|
while (len-- != 0){
|
//printf_tiny("0x%x, ",buf[len]);
|
//printf_tiny("0x%x, ",buf[len]);
|
write_byte_msb (buf[len]);
|
write_byte_msb (buf[len]);
|
}
|
}
|
}
|
}
|
|
|
/** \brief Internal: Reads one byte from the SPI bus
|
/** \brief Internal: Reads one byte from the SPI bus
|
*
|
*
|
* \return data read from the bus
|
* \return data read from the bus
|
*/
|
*/
|
#if 0
|
#if 0
|
/*
|
/*
|
* This is incorrectly compiled by SDCC 2.4.0
|
* This is incorrectly compiled by SDCC 2.4.0
|
*/
|
*/
|
/*static unsigned char
|
/*static unsigned char
|
read_byte_msb (void)
|
read_byte_msb (void)
|
{
|
{
|
unsigned char v = 0;
|
unsigned char v = 0;
|
|
|
bitSPI_CLK = 1;
|
bitSPI_CLK = 1;
|
v |= bitSPI_MISO;
|
v |= bitSPI_MISO;
|
bitSPI_CLK = 0;
|
bitSPI_CLK = 0;
|
|
|
v = v << 1;
|
v = v << 1;
|
bitSPI_CLK = 1;
|
bitSPI_CLK = 1;
|
v |= bitSPI_MISO;
|
v |= bitSPI_MISO;
|
bitSPI_CLK = 0;
|
bitSPI_CLK = 0;
|
|
|
v = v << 1;
|
v = v << 1;
|
bitSPI_CLK = 1;
|
bitSPI_CLK = 1;
|
v |= bitSPI_MISO;
|
v |= bitSPI_MISO;
|
bitSPI_CLK = 0;
|
bitSPI_CLK = 0;
|
|
|
v = v << 1;
|
v = v << 1;
|
bitSPI_CLK = 1;
|
bitSPI_CLK = 1;
|
v |= bitSPI_MISO;
|
v |= bitSPI_MISO;
|
bitSPI_CLK = 0;
|
bitSPI_CLK = 0;
|
|
|
v = v << 1;
|
v = v << 1;
|
bitSPI_CLK = 1;
|
bitSPI_CLK = 1;
|
v |= bitSPI_MISO;
|
v |= bitSPI_MISO;
|
bitSPI_CLK = 0;
|
bitSPI_CLK = 0;
|
|
|
v = v << 1;
|
v = v << 1;
|
bitSPI_CLK = 1;
|
bitSPI_CLK = 1;
|
v |= bitSPI_MISO;
|
v |= bitSPI_MISO;
|
bitSPI_CLK = 0;
|
bitSPI_CLK = 0;
|
|
|
v = v << 1;
|
v = v << 1;
|
bitSPI_CLK = 1;
|
bitSPI_CLK = 1;
|
v |= bitSPI_MISO;
|
v |= bitSPI_MISO;
|
bitSPI_CLK = 0;
|
bitSPI_CLK = 0;
|
|
|
v = v << 1;
|
v = v << 1;
|
bitSPI_CLK = 1;
|
bitSPI_CLK = 1;
|
v |= bitSPI_MISO;
|
v |= bitSPI_MISO;
|
bitSPI_CLK = 0;
|
bitSPI_CLK = 0;
|
|
|
return v;
|
return v;
|
} */
|
} */
|
#else
|
#else
|
static unsigned char
|
static unsigned char
|
read_byte_msb (void) _naked
|
read_byte_msb (void) _naked
|
{
|
{
|
_asm
|
_asm
|
clr a
|
clr a
|
|
|
setb _bitSPI_CLK
|
setb _bitSPI_CLK
|
mov c, _bitSPI_MISO
|
mov c, _bitSPI_MISO
|
rlc a
|
rlc a
|
clr _bitSPI_CLK
|
clr _bitSPI_CLK
|
|
|
setb _bitSPI_CLK
|
setb _bitSPI_CLK
|
mov c, _bitSPI_MISO
|
mov c, _bitSPI_MISO
|
rlc a
|
rlc a
|
clr _bitSPI_CLK
|
clr _bitSPI_CLK
|
|
|
setb _bitSPI_CLK
|
setb _bitSPI_CLK
|
mov c, _bitSPI_MISO
|
mov c, _bitSPI_MISO
|
rlc a
|
rlc a
|
clr _bitSPI_CLK
|
clr _bitSPI_CLK
|
|
|
setb _bitSPI_CLK
|
setb _bitSPI_CLK
|
mov c, _bitSPI_MISO
|
mov c, _bitSPI_MISO
|
rlc a
|
rlc a
|
clr _bitSPI_CLK
|
clr _bitSPI_CLK
|
|
|
setb _bitSPI_CLK
|
setb _bitSPI_CLK
|
mov c, _bitSPI_MISO
|
mov c, _bitSPI_MISO
|
rlc a
|
rlc a
|
clr _bitSPI_CLK
|
clr _bitSPI_CLK
|
|
|
setb _bitSPI_CLK
|
setb _bitSPI_CLK
|
mov c, _bitSPI_MISO
|
mov c, _bitSPI_MISO
|
rlc a
|
rlc a
|
clr _bitSPI_CLK
|
clr _bitSPI_CLK
|
|
|
setb _bitSPI_CLK
|
setb _bitSPI_CLK
|
mov c, _bitSPI_MISO
|
mov c, _bitSPI_MISO
|
rlc a
|
rlc a
|
clr _bitSPI_CLK
|
clr _bitSPI_CLK
|
|
|
setb _bitSPI_CLK
|
setb _bitSPI_CLK
|
mov c, _bitSPI_MISO
|
mov c, _bitSPI_MISO
|
rlc a
|
rlc a
|
clr _bitSPI_CLK
|
clr _bitSPI_CLK
|
|
|
mov dpl,a
|
mov dpl,a
|
ret
|
ret
|
_endasm;
|
_endasm;
|
}
|
}
|
#endif
|
#endif
|
|
|
static void
|
static void
|
read_bytes_msb (xdata unsigned char *buf, unsigned char len)
|
read_bytes_msb (xdata unsigned char *buf, unsigned char len)
|
{
|
{
|
while (len-- != 0){
|
while (len-- != 0){
|
*buf++ = read_byte_msb ();
|
*buf++ = read_byte_msb ();
|
}
|
}
|
}
|
}
|
|
|