Commit 6530f954 authored by TMRh20's avatar TMRh20

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
parent cd8bb19d
......@@ -37,4 +37,5 @@ Supported Boards:
* Mega Types (2560, 1280, etc)
* ARM (Arduino Due) via extended SPI methods
* ATTiny 24/44/84 25/45/85
* Raspberry Pi
* See the [documentation](http://tmrh20.github.io/) for more info
\ No newline at end of file
......@@ -409,14 +409,25 @@ bool RF24::begin(void)
{
debug = false;
//debug = true;
// This initialize the SPI bus with
// csn pin as chip select (custom or not)
// Init BCM2835 chipset for talking with us
if (!bcm2835_init()){
return false;
}
// Initialise the CE pin of NRF24 (chip enable)
bcm2835_gpio_fsel(ce_pin, BCM2835_GPIO_FSEL_OUTP);
bcm2835_gpio_write(ce_pin, LOW);
switch(csn_pin){ //Ensure valid hardware CS pin
case 0: break;
case 1: break;
case 8: csn_pin = 0; break;
case 7: csn_pin = 1; break;
default: csn_pin = 0; break;
}
bcm2835_spi_begin();
// used to drive custom I/O to trigger my logic analyser
// bcm2835_gpio_fsel(GPIO_CTRL_PIN , BCM2835_GPIO_FSEL_OUTP);
......@@ -429,12 +440,14 @@ bool RF24::begin(void)
// Set SPI bus Speed
bcm2835_spi_setClockDivider(spi_speed);
if(csn_pin <= BCM2835_SPI_CS_NONE){
// Choose hardware CSN pin
bcm2835_spi_chipSelect(csn_pin);
}
// This initialize the SPI bus with
// csn pin as chip select (custom or not)
bcm2835_spi_begin(csn_pin);
// Initialise the CE pin of NRF24 (chip enable) after the CSN pin, so that
// The input mode is not changed if using one of the hardware CE pins
bcm2835_gpio_fsel(ce_pin, BCM2835_GPIO_FSEL_OUTP);
bcm2835_gpio_write(ce_pin, LOW);
// wait 100ms
delay(100);
......@@ -544,7 +557,7 @@ void RF24::powerUp(void)
bool RF24::write( const void* buf, uint8_t len, const bool multicast ){
// Begin the write
startWrite(buf,len, multicast);
startFastWrite(buf,len, multicast);
//Wait until complete or failed
......@@ -655,11 +668,11 @@ void RF24::startWrite( const void* buf, uint8_t len, const bool multicast )
{
// Send the payload
write_payload( buf, len,multicast ? W_TX_PAYLOAD_NO_ACK : W_TX_PAYLOAD ) ;
write_payload( buf, len,multicast ? W_TX_PAYLOAD_NO_ACK : W_TX_PAYLOAD ) ;
bcm2835_gpio_write(ce_pin, HIGH);
//bcm2835_gpio_write(ce_pin, LOW);
delayMicroseconds(10);
bcm2835_gpio_write(ce_pin, LOW);
}
/****************************************************************************/
......
......@@ -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 ;
......@@ -460,82 +460,22 @@ 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_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(RPI_GPIO_P1_26, BCM2835_GPIO_FSEL_ALT0); // CE1
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
// 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_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
volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4;
bcm2835_peri_write(paddr, 0); // All 0s
// Clear TX and RX fifos
......@@ -544,7 +484,7 @@ void bcm2835_spi_begin(uint8_t cs)
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)
......@@ -608,9 +547,10 @@ uint8_t bcm2835_spi_transfer(uint8_t value)
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?
......@@ -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;
}
......@@ -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?
......@@ -733,9 +673,9 @@ 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);
}
......
......@@ -1107,7 +1107,7 @@ extern "C" {
/// You should call bcm2835_spi_end() when all SPI funcitons are complete to return the pins to
/// their default functions
/// \sa bcm2835_spi_end()
extern void bcm2835_spi_begin(uint8_t cs);
extern void bcm2835_spi_begin();
/// End SPI operations.
/// SPI0 pins P1-19 (MOSI), P1-21 (MISO), P1-23 (CLK), P1-24 (CE0) and P1-26 (CE1)
......
......@@ -32,15 +32,14 @@ using namespace std;
// CE Pin, CSN Pin, SPI Speed
// Setup for GPIO 22 CE and GPIO 25 CSN with SPI Speed @ 1Mhz
//RF24 radio(RPI_V2_GPIO_P1_22, RPI_V2_GPIO_P1_18, BCM2835_SPI_SPEED_1MHZ);
// Setup for GPIO 22 CE and CE1 CSN with SPI Speed @ 1Mhz
//RF24 radio(RPI_V2_GPIO_P1_22, RPI_V2_GPIO_P1_26, BCM2835_SPI_SPEED_1MHZ);
// Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 4Mhz
//RF24 radio(RPI_V2_GPIO_P1_15, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_4MHZ);
// Setup for GPIO 22 CE and CE1 CSN with SPI Speed @ 8Mhz
//RF24 radio(RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_26, BCM2835_SPI_SPEED_8MHZ);
RF24 radio(RPI_V2_GPIO_P1_15,BCM2835_SPI_CS0, BCM2835_SPI_SPEED_8MHZ);
// Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 8Mhz
RF24 radio(RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_24, BCM2835_SPI_SPEED_8MHZ);
......
......@@ -27,15 +27,14 @@ using namespace std;
// CE Pin, CSN Pin, SPI Speed
// Setup for GPIO 22 CE and GPIO 25 CSN with SPI Speed @ 1Mhz
//RF24 radio(RPI_V2_GPIO_P1_22, RPI_V2_GPIO_P1_18, BCM2835_SPI_SPEED_1MHZ);
// Setup for GPIO 22 CE and CE1 CSN with SPI Speed @ 1Mhz
//RF24 radio(RPI_V2_GPIO_P1_22, RPI_V2_GPIO_P1_26, BCM2835_SPI_SPEED_1MHZ);
// Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 4Mhz
//RF24 radio(RPI_V2_GPIO_P1_15, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_4MHZ);
// Setup for GPIO 22 CE and CE1 CSN with SPI Speed @ 8Mhz
RF24 radio(RPI_V2_GPIO_P1_15, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_8MHZ);
// Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 8Mhz
RF24 radio(RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_24, BCM2835_SPI_SPEED_8MHZ);
// Radio pipe addresses for the 2 nodes to communicate.
......
......@@ -22,14 +22,14 @@ using namespace std;
// CE Pin, CSN Pin, SPI Speed
// Setup for GPIO 22 CE and GPIO 25 CSN with SPI Speed @ 1Mhz
//RF24 radio(RPI_V2_GPIO_P1_22, RPI_V2_GPIO_P1_18, BCM2835_SPI_SPEED_1MHZ);
// Setup for GPIO 22 CE and CE1 CSN with SPI Speed @ 1Mhz
//RF24 radio(RPI_V2_GPIO_P1_22, RPI_V2_GPIO_P1_26, BCM2835_SPI_SPEED_1MHZ);
// Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 4Mhz
//RF24 radio(RPI_V2_GPIO_P1_15, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_4MHZ);
// Setup for GPIO 22 CE and CE1 CSN with SPI Speed @ 8Mhz
RF24 radio(RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_26, BCM2835_SPI_SPEED_8MHZ);
// Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 8Mhz
RF24 radio(RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_24, BCM2835_SPI_SPEED_8MHZ);
// Radio pipe addresses for the 2 nodes to communicate.
......
......@@ -26,14 +26,14 @@ using namespace std;
// CE Pin, CSN Pin, SPI Speed
// Setup for GPIO 22 CE and GPIO 25 CSN with SPI Speed @ 1Mhz
//RF24 radio(RPI_V2_GPIO_P1_22, RPI_V2_GPIO_P1_18, BCM2835_SPI_SPEED_1MHZ);
// Setup for GPIO 22 CE and CE1 CSN with SPI Speed @ 1Mhz
//RF24 radio(RPI_V2_GPIO_P1_22, RPI_V2_GPIO_P1_26, BCM2835_SPI_SPEED_1MHZ);
// Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 4Mhz
//RF24 radio(RPI_V2_GPIO_P1_15, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_4MHZ);
// Setup for GPIO 22 CE and CE1 CSN with SPI Speed @ 8Mhz
RF24 radio(RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_26, BCM2835_SPI_SPEED_8MHZ);
// Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 8Mhz
RF24 radio(RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_24, BCM2835_SPI_SPEED_8MHZ);
......
......@@ -75,23 +75,32 @@ Connection Info
Using pin 15/GPIO 22 for CE, pin 24/GPIO8 (CE0) for CSN
Can use either RPi CE0 or CE1 pins for radio CSN.
Choose any RPi output pin for radio CE pin.
**Constructor:**
```
RF24 radio(RPI_V2_GPIO_P1_15,BCM2835_SPI_CS0, BCM2835_SPI_SPEED_8MHZ);
or
RF24 radio(RPI_V2_GPIO_P1_15,BCM2835_SPI_CS1, BCM2835_SPI_SPEED_8MHZ);
```
**Pins:**
|NRF24L01 | RPI | P1 Connector |
|----- |----------- | -------------|
|VCC: | rpi-3v3 | (17) |
|GND: | rpi-gnd | (25) |
|CE: | rpi-gpio22 | (15) |
|CSN: | rpi-gpio8 | (24) |
|SCK: | rpi-sckl | (23) |
|MOSI: | rpi-mosi | (19) |
|MISO: | rpi-miso | (21) |
|-----|-----------|-------------|
| VCC | rpi-3v3 | (17) |
| GND | rpi-gnd | (25) |
| CE | rpi-gpio22 | (15) |
| CSN | rpi-gpio8 | (24) |
| SCK | rpi-sckl | (23) |
| MOSI | rpi-mosi | (19) |
| MISO | rpi-miso | (21) |
See http://www.airspayce.com/mikem/bcm2835/index.html for BCM2835 class documentation.
Note: The BCM library has been customized slightly to allow use of hardware CE pins not
in use for SPI, and to include a millis() function.
****************
......
......@@ -75,23 +75,32 @@ Connection Info
Using pin 15/GPIO 22 for CE, pin 24/GPIO8 (CE0) for CSN
Can use either RPi CE0 or CE1 pins for radio CSN.
Choose any RPi output pin for radio CE pin.
**Constructor:**
```
RF24 radio(RPI_V2_GPIO_P1_15,BCM2835_SPI_CS0, BCM2835_SPI_SPEED_8MHZ);
or
RF24 radio(RPI_V2_GPIO_P1_15,BCM2835_SPI_CS1, BCM2835_SPI_SPEED_8MHZ);
```
**Pins:**
|NRF24L01 | RPI | P1 Connector |
|----- |----------- | -------------|
|VCC: | rpi-3v3 | (17) |
|GND: | rpi-gnd | (25) |
|CE: | rpi-gpio22 | (15) |
|CSN: | rpi-gpio8 | (24) |
|SCK: | rpi-sckl | (23) |
|MOSI: | rpi-mosi | (19) |
|MISO: | rpi-miso | (21) |
|-----|-----------|-------------|
| VCC | rpi-3v3 | (17) |
| GND | rpi-gnd | (25) |
| CE | rpi-gpio22 | (15) |
| CSN | rpi-gpio8 | (24) |
| SCK | rpi-sckl | (23) |
| MOSI | rpi-mosi | (19) |
| MISO | rpi-miso | (21) |
See http://www.airspayce.com/mikem/bcm2835/index.html for BCM2835 class documentation.
Note: The BCM library has been customized slightly to allow use of hardware CE pins not
in use for SPI, and to include a millis() function.
****************
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment