RPi SPI functionality and RPi fix for startWrite
- Enabled use of hardware CS1 pin - Removed custom_cs code for software driven CSN - Modified BCM driver to allow use of hardware SPI pins not in use while SPI is active. - Updated constructor in examples
This commit is contained in:
+93
-145
@@ -59,7 +59,7 @@ static uint8_t debug = 0;
|
||||
static int i2c_byte_wait_us = 0;
|
||||
|
||||
// SPI Custom Chip Select Pin
|
||||
static int spi_custom_cs = 0;
|
||||
//static int spi_custom_cs = 0;
|
||||
|
||||
// Time for millis()
|
||||
static unsigned long long epoch ;
|
||||
@@ -365,7 +365,7 @@ void bcm2835_gpio_set_pad(uint8_t group, uint32_t control)
|
||||
void bcm2835_delay(unsigned int millis)
|
||||
{
|
||||
struct timespec sleeper;
|
||||
|
||||
|
||||
sleeper.tv_sec = (time_t)(millis / 1000);
|
||||
sleeper.tv_nsec = (long)(millis % 1000) * 1000000;
|
||||
nanosleep(&sleeper, NULL);
|
||||
@@ -376,18 +376,18 @@ void bcm2835_delayMicroseconds(uint64_t micros)
|
||||
{
|
||||
struct timespec t1;
|
||||
uint64_t start;
|
||||
|
||||
|
||||
// Calling nanosleep() takes at least 100-200 us, so use it for
|
||||
// long waits and use a busy wait on the System Timer for the rest.
|
||||
start = bcm2835_st_read();
|
||||
|
||||
|
||||
if (micros > 450)
|
||||
{
|
||||
t1.tv_sec = 0;
|
||||
t1.tv_nsec = 1000 * (long)(micros - 200);
|
||||
nanosleep(&t1, NULL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bcm2835_st_delay(start, micros);
|
||||
}
|
||||
|
||||
@@ -460,91 +460,31 @@ void bcm2835_gpio_set_pud(uint8_t pin, uint8_t pud)
|
||||
bcm2835_gpio_pudclk(pin, 0);
|
||||
}
|
||||
|
||||
void bcm2835_spi_begin(uint8_t cs)
|
||||
void bcm2835_spi_begin()
|
||||
{
|
||||
/*
|
||||
|
||||
// Set the SPI0 pins to the Alt 0 function to enable SPI0 access on them
|
||||
bcm2835_gpio_fsel(RPI_GPIO_P1_26, BCM2835_GPIO_FSEL_ALT0); // CE1
|
||||
//bcm2835_gpio_fsel(RPI_GPIO_P1_26, BCM2835_GPIO_FSEL_ALT0); // CE1
|
||||
|
||||
// Enable CE0 by default, will be disabled if bcm2835_chipSelect() is called using another pin
|
||||
bcm2835_gpio_fsel(RPI_GPIO_P1_24, BCM2835_GPIO_FSEL_ALT0); // CE0
|
||||
|
||||
|
||||
|
||||
|
||||
bcm2835_gpio_fsel(RPI_GPIO_P1_21, BCM2835_GPIO_FSEL_ALT0); // MISO
|
||||
bcm2835_gpio_fsel(RPI_GPIO_P1_19, BCM2835_GPIO_FSEL_ALT0); // MOSI
|
||||
bcm2835_gpio_fsel(RPI_GPIO_P1_23, BCM2835_GPIO_FSEL_ALT0); // CLK
|
||||
|
||||
|
||||
// Set the SPI CS register to the some sensible defaults
|
||||
volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4;
|
||||
bcm2835_peri_write(paddr, 0); // All 0s
|
||||
|
||||
|
||||
// Clear TX and RX fifos
|
||||
bcm2835_peri_write_nb(paddr, BCM2835_SPI0_CS_CLEAR);
|
||||
*/
|
||||
|
||||
volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4;
|
||||
// Set the SPI0 pins to the Alt 0 function to enable SPI0 access on them
|
||||
// except if we need custom Chip Select Pin
|
||||
// printf("bcm2835_spi_begin -> spi_custom_cs = %d \n",cs );
|
||||
|
||||
// Do we need custom chip select control or
|
||||
// drive CE1 manually (because CE1 does not work with hardware)
|
||||
if ( cs > BCM2835_SPI_CS_NONE || cs == BCM2835_SPI_CS1 )
|
||||
{
|
||||
// indicate we will use a custom GPIO port
|
||||
spi_custom_cs = cs ;
|
||||
|
||||
// ok hard CE1 not working, drive it manually
|
||||
if (cs == BCM2835_SPI_CS1 )
|
||||
{
|
||||
// Dirty Hack CE1 in now custom Chip Select GPIO 26
|
||||
// the real CE1 pin
|
||||
spi_custom_cs = RPI_GPIO_P1_26 ;
|
||||
|
||||
bcm2835_gpio_fsel(spi_custom_cs, BCM2835_GPIO_FSEL_OUTP);
|
||||
bcm2835_gpio_write(spi_custom_cs, HIGH);
|
||||
}
|
||||
|
||||
// Mask in we use custom CS (not sure it has a real effect)
|
||||
bcm2835_peri_set_bits(paddr, BCM2835_SPI_CS_NONE, BCM2835_SPI0_CS_CS);
|
||||
}
|
||||
// Ok hardware driving of chip select
|
||||
else
|
||||
{
|
||||
// Just in case
|
||||
spi_custom_cs = 0 ;
|
||||
|
||||
// Mask in the CS bits of CS
|
||||
bcm2835_peri_set_bits(paddr, cs, BCM2835_SPI0_CS_CS);
|
||||
}
|
||||
|
||||
// Now we can drive the I/O as asked
|
||||
if (spi_custom_cs == 0)
|
||||
{
|
||||
// Not custom CS, so hardware driven
|
||||
bcm2835_gpio_fsel(RPI_GPIO_P1_24, BCM2835_GPIO_FSEL_ALT0); // CE0
|
||||
bcm2835_gpio_fsel(RPI_GPIO_P1_26, BCM2835_GPIO_FSEL_ALT0); // CE1
|
||||
}
|
||||
else
|
||||
{
|
||||
// so set custom CS as output, High level by default
|
||||
bcm2835_gpio_fsel(spi_custom_cs, BCM2835_GPIO_FSEL_OUTP); // Custom GPIO
|
||||
bcm2835_gpio_write(spi_custom_cs, HIGH);
|
||||
}
|
||||
|
||||
// Classic pin, hardware driven
|
||||
bcm2835_gpio_fsel(RPI_GPIO_P1_21, BCM2835_GPIO_FSEL_ALT0); // MISO
|
||||
bcm2835_gpio_fsel(RPI_GPIO_P1_19, BCM2835_GPIO_FSEL_ALT0); // MOSI
|
||||
bcm2835_gpio_fsel(RPI_GPIO_P1_23, BCM2835_GPIO_FSEL_ALT0); // CLK
|
||||
|
||||
// Set the SPI CS register to the some sensible defaults
|
||||
bcm2835_peri_write(paddr, 0); // All 0s
|
||||
|
||||
// Clear TX and RX fifos
|
||||
bcm2835_peri_write_nb(paddr, BCM2835_SPI0_CS_CLEAR);
|
||||
}
|
||||
|
||||
void bcm2835_spi_end(void)
|
||||
{
|
||||
// Set all the SPI0 pins back to input
|
||||
{
|
||||
/* // Set all the SPI0 pins back to input
|
||||
if (spi_custom_cs == 0)
|
||||
{
|
||||
bcm2835_gpio_fsel(RPI_GPIO_P1_26, BCM2835_GPIO_FSEL_INPT); // CE1
|
||||
@@ -557,26 +497,25 @@ void bcm2835_spi_end(void)
|
||||
bcm2835_gpio_fsel(RPI_GPIO_P1_21, BCM2835_GPIO_FSEL_INPT); // MISO
|
||||
bcm2835_gpio_fsel(RPI_GPIO_P1_19, BCM2835_GPIO_FSEL_INPT); // MOSI
|
||||
bcm2835_gpio_fsel(RPI_GPIO_P1_23, BCM2835_GPIO_FSEL_INPT); // CLK
|
||||
|
||||
/*
|
||||
*/
|
||||
|
||||
// Set all the SPI0 pins back to input
|
||||
bcm2835_gpio_fsel(RPI_GPIO_P1_26, BCM2835_GPIO_FSEL_INPT); // CE1
|
||||
bcm2835_gpio_fsel(RPI_GPIO_P1_24, BCM2835_GPIO_FSEL_INPT); // CE0
|
||||
bcm2835_gpio_fsel(RPI_GPIO_P1_21, BCM2835_GPIO_FSEL_INPT); // MISO
|
||||
bcm2835_gpio_fsel(RPI_GPIO_P1_19, BCM2835_GPIO_FSEL_INPT); // MOSI
|
||||
bcm2835_gpio_fsel(RPI_GPIO_P1_23, BCM2835_GPIO_FSEL_INPT); // CLK
|
||||
*/
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
// Drive Custom chip select pin
|
||||
void bcm2835_spi_setChipSelect(uint8_t level)
|
||||
{
|
||||
// Do this only if we are using custom ChipSelect I/O
|
||||
if ( spi_custom_cs > BCM2835_SPI_CS_NONE )
|
||||
bcm2835_gpio_write(spi_custom_cs, level);
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
void bcm2835_spi_setBitOrder(uint8_t order)
|
||||
@@ -606,14 +545,15 @@ uint8_t bcm2835_spi_transfer(uint8_t value)
|
||||
{
|
||||
volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4;
|
||||
volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4;
|
||||
|
||||
|
||||
// Custom chip select LOW
|
||||
if(spi_custom_cs > BCM2835_SPI_CS_NONE){
|
||||
/*if(spi_custom_cs > BCM2835_SPI_CS_NONE){
|
||||
bcm2835_spi_setChipSelect(LOW);
|
||||
}
|
||||
}*/
|
||||
|
||||
// This is Polled transfer as per section 10.6.1
|
||||
// BUG ALERT: what happens if we get interupted in this section, and someone else
|
||||
// accesses a different peripheral?
|
||||
// accesses a different peripheral?
|
||||
// Clear TX and RX fifos
|
||||
bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR);
|
||||
|
||||
@@ -640,9 +580,9 @@ uint8_t bcm2835_spi_transfer(uint8_t value)
|
||||
bcm2835_peri_set_bits(paddr, 0, BCM2835_SPI0_CS_TA);
|
||||
|
||||
// Custom chip select HIGH
|
||||
if(spi_custom_cs > BCM2835_SPI_CS_NONE){
|
||||
bcm2835_spi_setChipSelect(HIGH);
|
||||
}
|
||||
//if(spi_custom_cs > BCM2835_SPI_CS_NONE){
|
||||
// bcm2835_spi_setChipSelect(HIGH);
|
||||
//}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -656,7 +596,7 @@ void bcm2835_spi_transfernb(char* tbuf, char* rbuf, uint32_t len)
|
||||
|
||||
// This is Polled transfer as per section 10.6.1
|
||||
// BUG ALERT: what happens if we get interupted in this section, and someone else
|
||||
// accesses a different peripheral?
|
||||
// accesses a different peripheral?
|
||||
|
||||
// Clear TX and RX fifos
|
||||
bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR);
|
||||
@@ -696,9 +636,9 @@ void bcm2835_spi_writenb(char* tbuf, uint32_t len)
|
||||
volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4;
|
||||
volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4;
|
||||
|
||||
if(spi_custom_cs > BCM2835_SPI_CS_NONE){
|
||||
bcm2835_spi_setChipSelect(LOW);
|
||||
}
|
||||
//if(spi_custom_cs > BCM2835_SPI_CS_NONE){
|
||||
// bcm2835_spi_setChipSelect(LOW);
|
||||
//}
|
||||
// This is Polled transfer as per section 10.6.1
|
||||
// BUG ALERT: what happens if we get interupted in this section, and someone else
|
||||
// accesses a different peripheral?
|
||||
@@ -715,15 +655,15 @@ void bcm2835_spi_writenb(char* tbuf, uint32_t len)
|
||||
// Maybe wait for TXD
|
||||
while (!(bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD))
|
||||
;
|
||||
|
||||
|
||||
// Write to FIFO, no barrier
|
||||
bcm2835_peri_write_nb(fifo, tbuf[i]);
|
||||
|
||||
|
||||
// Read from FIFO to prevent stalling
|
||||
while (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD)
|
||||
(void) bcm2835_peri_read_nb(fifo);
|
||||
}
|
||||
|
||||
|
||||
// Wait for DONE to be set
|
||||
while (!(bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE)) {
|
||||
while (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD)
|
||||
@@ -732,10 +672,10 @@ void bcm2835_spi_writenb(char* tbuf, uint32_t len)
|
||||
|
||||
// Set TA = 0, and also set the barrier
|
||||
bcm2835_peri_set_bits(paddr, 0, BCM2835_SPI0_CS_TA);
|
||||
|
||||
if(spi_custom_cs > BCM2835_SPI_CS_NONE){
|
||||
bcm2835_spi_setChipSelect(HIGH);
|
||||
}
|
||||
|
||||
//if(spi_custom_cs > BCM2835_SPI_CS_NONE){
|
||||
// bcm2835_spi_setChipSelect(HIGH);
|
||||
//}
|
||||
}
|
||||
|
||||
// Writes (and reads) an number of bytes to SPI
|
||||
@@ -748,6 +688,14 @@ void bcm2835_spi_transfern(char* buf, uint32_t len)
|
||||
void bcm2835_spi_chipSelect(uint8_t cs)
|
||||
{
|
||||
volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4;
|
||||
|
||||
if(cs){
|
||||
bcm2835_gpio_fsel(RPI_GPIO_P1_26, BCM2835_GPIO_FSEL_ALT0); // CE1
|
||||
bcm2835_gpio_fsel(RPI_GPIO_P1_24, BCM2835_GPIO_FSEL_INPT); // Revert default of CE0 back to input
|
||||
}else{
|
||||
bcm2835_gpio_fsel(RPI_GPIO_P1_24, BCM2835_GPIO_FSEL_ALT0); // CE0
|
||||
}
|
||||
|
||||
// Mask in the CS bits of CS
|
||||
bcm2835_peri_set_bits(paddr, cs, BCM2835_SPI0_CS_CS);
|
||||
}
|
||||
@@ -772,7 +720,7 @@ void bcm2835_i2c_begin(void)
|
||||
// Set the I2C/BSC1 pins to the Alt 0 function to enable I2C access on them
|
||||
bcm2835_gpio_fsel(RPI_V2_GPIO_P1_03, BCM2835_GPIO_FSEL_ALT0); // SDA
|
||||
bcm2835_gpio_fsel(RPI_V2_GPIO_P1_05, BCM2835_GPIO_FSEL_ALT0); // SCL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Read the clock divider register
|
||||
uint16_t cdiv = bcm2835_peri_read(paddr);
|
||||
@@ -800,7 +748,7 @@ void bcm2835_i2c_setSlaveAddress(uint8_t addr)
|
||||
// Set I2C Device Address
|
||||
#ifdef I2C_V1
|
||||
volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_A/4;
|
||||
#else
|
||||
#else
|
||||
volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_A/4;
|
||||
#endif
|
||||
bcm2835_peri_write(paddr, addr);
|
||||
@@ -815,7 +763,7 @@ void bcm2835_i2c_setClockDivider(uint16_t divider)
|
||||
volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_DIV/4;
|
||||
#else
|
||||
volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_DIV/4;
|
||||
#endif
|
||||
#endif
|
||||
bcm2835_peri_write(paddr, divider);
|
||||
// Calculate time for transmitting one byte
|
||||
// 1000000 = micros seconds in a second
|
||||
@@ -845,7 +793,7 @@ uint8_t bcm2835_i2c_write(const char * buf, uint32_t len)
|
||||
volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4;
|
||||
volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4;
|
||||
volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
uint32_t remaining = len;
|
||||
uint32_t i = 0;
|
||||
@@ -864,10 +812,10 @@ uint8_t bcm2835_i2c_write(const char * buf, uint32_t len)
|
||||
i++;
|
||||
remaining--;
|
||||
}
|
||||
|
||||
|
||||
// Enable device and start transfer
|
||||
bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST);
|
||||
|
||||
|
||||
// Transfer is over when BCM2835_BSC_S_DONE
|
||||
while(!(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE ))
|
||||
{
|
||||
@@ -916,7 +864,7 @@ uint8_t bcm2835_i2c_read(char* buf, uint32_t len)
|
||||
volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4;
|
||||
volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4;
|
||||
volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
uint32_t remaining = len;
|
||||
uint32_t i = 0;
|
||||
@@ -930,7 +878,7 @@ uint8_t bcm2835_i2c_read(char* buf, uint32_t len)
|
||||
bcm2835_peri_write_nb(dlen, len);
|
||||
// Start read
|
||||
bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ);
|
||||
|
||||
|
||||
// wait for transfer to complete
|
||||
while (!(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE))
|
||||
{
|
||||
@@ -943,7 +891,7 @@ uint8_t bcm2835_i2c_read(char* buf, uint32_t len)
|
||||
remaining--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// transfer has finished - grab any remaining stuff in FIFO
|
||||
while (remaining && (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD))
|
||||
{
|
||||
@@ -952,7 +900,7 @@ uint8_t bcm2835_i2c_read(char* buf, uint32_t len)
|
||||
i++;
|
||||
remaining--;
|
||||
}
|
||||
|
||||
|
||||
// Received a NACK
|
||||
if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR)
|
||||
{
|
||||
@@ -979,7 +927,7 @@ uint8_t bcm2835_i2c_read(char* buf, uint32_t len)
|
||||
// Read an number of bytes from I2C sending a repeated start after writing
|
||||
// the required register. Only works if your device supports this mode
|
||||
uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len)
|
||||
{
|
||||
{
|
||||
#ifdef I2C_V1
|
||||
volatile uint32_t* dlen = bcm2835_bsc0 + BCM2835_BSC_DLEN/4;
|
||||
volatile uint32_t* fifo = bcm2835_bsc0 + BCM2835_BSC_FIFO/4;
|
||||
@@ -990,11 +938,11 @@ uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len)
|
||||
volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4;
|
||||
volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4;
|
||||
volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4;
|
||||
#endif
|
||||
#endif
|
||||
uint32_t remaining = len;
|
||||
uint32_t i = 0;
|
||||
uint8_t reason = BCM2835_I2C_REASON_OK;
|
||||
|
||||
|
||||
// Clear FIFO
|
||||
bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 );
|
||||
// Clear Status
|
||||
@@ -1005,7 +953,7 @@ uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len)
|
||||
bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN);
|
||||
bcm2835_peri_write_nb(fifo, regaddr[0]);
|
||||
bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST);
|
||||
|
||||
|
||||
// poll for transfer has started
|
||||
while ( !( bcm2835_peri_read_nb(status) & BCM2835_BSC_S_TA ) )
|
||||
{
|
||||
@@ -1013,14 +961,14 @@ uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len)
|
||||
if(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Send a repeated start with read bit set in address
|
||||
bcm2835_peri_write_nb(dlen, len);
|
||||
bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ );
|
||||
|
||||
// Wait for write to complete and first byte back.
|
||||
|
||||
// Wait for write to complete and first byte back.
|
||||
bcm2835_delayMicroseconds(i2c_byte_wait_us * 3);
|
||||
|
||||
|
||||
// wait for transfer to complete
|
||||
while (!(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE))
|
||||
{
|
||||
@@ -1033,7 +981,7 @@ uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len)
|
||||
remaining--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// transfer has finished - grab any remaining stuff in FIFO
|
||||
while (remaining && (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD))
|
||||
{
|
||||
@@ -1042,7 +990,7 @@ uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len)
|
||||
i++;
|
||||
remaining--;
|
||||
}
|
||||
|
||||
|
||||
// Received a NACK
|
||||
if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR)
|
||||
{
|
||||
@@ -1066,10 +1014,10 @@ uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len)
|
||||
return reason;
|
||||
}
|
||||
|
||||
// Sending an arbitrary number of bytes before issuing a repeated start
|
||||
// Sending an arbitrary number of bytes before issuing a repeated start
|
||||
// (with no prior stop) and reading a response. Some devices require this behavior.
|
||||
uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint32_t buf_len)
|
||||
{
|
||||
{
|
||||
#ifdef I2C_V1
|
||||
volatile uint32_t* dlen = bcm2835_bsc0 + BCM2835_BSC_DLEN/4;
|
||||
volatile uint32_t* fifo = bcm2835_bsc0 + BCM2835_BSC_FIFO/4;
|
||||
@@ -1080,12 +1028,12 @@ uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint
|
||||
volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4;
|
||||
volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4;
|
||||
volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
uint32_t remaining = cmds_len;
|
||||
uint32_t i = 0;
|
||||
uint8_t reason = BCM2835_I2C_REASON_OK;
|
||||
|
||||
|
||||
// Clear FIFO
|
||||
bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 );
|
||||
|
||||
@@ -1094,7 +1042,7 @@ uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint
|
||||
|
||||
// Set Data Length
|
||||
bcm2835_peri_write_nb(dlen, cmds_len);
|
||||
|
||||
|
||||
// pre populate FIFO with max buffer
|
||||
while( remaining && ( i < BCM2835_BSC_FIFO_SIZE ) )
|
||||
{
|
||||
@@ -1103,9 +1051,9 @@ uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint
|
||||
remaining--;
|
||||
}
|
||||
|
||||
// Enable device and start transfer
|
||||
// Enable device and start transfer
|
||||
bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST);
|
||||
|
||||
|
||||
// poll for transfer has started (way to do repeated start, from BCM2835 datasheet)
|
||||
while ( !( bcm2835_peri_read_nb(status) & BCM2835_BSC_S_TA ) )
|
||||
{
|
||||
@@ -1113,17 +1061,17 @@ uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint
|
||||
if(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
remaining = buf_len;
|
||||
i = 0;
|
||||
|
||||
// Send a repeated start with read bit set in address
|
||||
bcm2835_peri_write_nb(dlen, buf_len);
|
||||
bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ );
|
||||
|
||||
// Wait for write to complete and first byte back.
|
||||
|
||||
// Wait for write to complete and first byte back.
|
||||
bcm2835_delayMicroseconds(i2c_byte_wait_us * (cmds_len + 1));
|
||||
|
||||
|
||||
// wait for transfer to complete
|
||||
while (!(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE))
|
||||
{
|
||||
@@ -1136,7 +1084,7 @@ uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint
|
||||
remaining--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// transfer has finished - grab any remaining stuff in FIFO
|
||||
while (remaining && (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD))
|
||||
{
|
||||
@@ -1145,7 +1093,7 @@ uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint
|
||||
i++;
|
||||
remaining--;
|
||||
}
|
||||
|
||||
|
||||
// Received a NACK
|
||||
if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR)
|
||||
{
|
||||
@@ -1202,7 +1150,7 @@ void bcm2835_pwm_set_clock(uint32_t divisor)
|
||||
bcm2835_delay(110); // Prevents clock going slow
|
||||
// Wait for the clock to be not busy
|
||||
while ((bcm2835_peri_read(bcm2835_clk + BCM2835_PWMCLK_CNTL) & 0x80) != 0)
|
||||
bcm2835_delay(1);
|
||||
bcm2835_delay(1);
|
||||
// set the clock divider and enable PWM clock
|
||||
bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_DIV, BCM2835_PWM_PASSWRD | (divisor << 12));
|
||||
bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_CNTL, BCM2835_PWM_PASSWRD | 0x11); // Source=osc and enable
|
||||
@@ -1288,7 +1236,7 @@ int bcm2835_init(void)
|
||||
{
|
||||
struct timeval tv ;
|
||||
|
||||
if (debug)
|
||||
if (debug)
|
||||
{
|
||||
bcm2835_pads = (uint32_t*)BCM2835_GPIO_PADS;
|
||||
bcm2835_clk = (uint32_t*)BCM2835_CLOCK_BASE;
|
||||
@@ -1303,13 +1251,13 @@ int bcm2835_init(void)
|
||||
int memfd = -1;
|
||||
int ok = 0;
|
||||
// Open the master /dev/memory device
|
||||
if ((memfd = open("/dev/mem", O_RDWR | O_SYNC) ) < 0)
|
||||
if ((memfd = open("/dev/mem", O_RDWR | O_SYNC) ) < 0)
|
||||
{
|
||||
fprintf(stderr, "bcm2835_init: Unable to open /dev/mem: %s\n",
|
||||
strerror(errno)) ;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
||||
// GPIO:
|
||||
bcm2835_gpio = (volatile uint32_t *)mapmem("gpio", BCM2835_BLOCK_SIZE, memfd, BCM2835_GPIO_BASE);
|
||||
if (bcm2835_gpio == MAP_FAILED) goto exit;
|
||||
@@ -1321,10 +1269,10 @@ int bcm2835_init(void)
|
||||
// Clock control (needed for PWM)
|
||||
bcm2835_clk = (volatile uint32_t *)mapmem("clk", BCM2835_BLOCK_SIZE, memfd, BCM2835_CLOCK_BASE);
|
||||
if (bcm2835_clk == MAP_FAILED) goto exit;
|
||||
|
||||
|
||||
bcm2835_pads = (volatile uint32_t *)mapmem("pads", BCM2835_BLOCK_SIZE, memfd, BCM2835_GPIO_PADS);
|
||||
if (bcm2835_pads == MAP_FAILED) goto exit;
|
||||
|
||||
|
||||
bcm2835_spi0 = (volatile uint32_t *)mapmem("spi0", BCM2835_BLOCK_SIZE, memfd, BCM2835_SPI0_BASE);
|
||||
if (bcm2835_spi0 == MAP_FAILED) goto exit;
|
||||
|
||||
@@ -1367,10 +1315,10 @@ int bcm2835_close(void)
|
||||
unmapmem((void**) &bcm2835_st, BCM2835_BLOCK_SIZE);
|
||||
unmapmem((void**) &bcm2835_pads, BCM2835_BLOCK_SIZE);
|
||||
return 1; // Success
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BCM2835_TEST
|
||||
// this is a simple test program that prints out what it will do rather than
|
||||
// this is a simple test program that prints out what it will do rather than
|
||||
// actually doing it
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
@@ -1398,13 +1346,13 @@ int main(int argc, char **argv)
|
||||
{
|
||||
// Turn it on
|
||||
bcm2835_gpio_write(RPI_GPIO_P1_11, HIGH);
|
||||
|
||||
|
||||
// wait a bit
|
||||
bcm2835_delay(500);
|
||||
|
||||
|
||||
// turn it off
|
||||
bcm2835_gpio_write(RPI_GPIO_P1_11, LOW);
|
||||
|
||||
|
||||
// wait a bit
|
||||
bcm2835_delay(500);
|
||||
}
|
||||
@@ -1417,7 +1365,7 @@ int main(int argc, char **argv)
|
||||
// Read some data
|
||||
uint8_t value = bcm2835_gpio_lev(RPI_GPIO_P1_15);
|
||||
printf("read from pin 15: %d\n", value);
|
||||
|
||||
|
||||
// wait a bit
|
||||
bcm2835_delay(500);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user