Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
R
RF24
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
xpstem
RF24
Commits
f06ca7cb
Commit
f06ca7cb
authored
Feb 12, 2015
by
TMRh20
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #72 from mannkind/Updates
Potential RPi 2 support via updated bcm2835.c (version 1.39)
parents
e7deb684
25d379c1
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
307 additions
and
246 deletions
+307
-246
RPi/bcm2835.c
RPi/bcm2835.c
+183
-155
RPi/bcm2835.h
RPi/bcm2835.h
+124
-91
No files found.
RPi/bcm2835.c
View file @
f06ca7cb
...
...
@@ -40,16 +40,23 @@
// By default I2C code is generated for the V2 RPi which has SDA1 and SCL1 connected.
// #define I2C_V1
// Pointers to the hardware register bases
volatile
uint32_t
*
bcm2835_gpio
=
(
volatile
uint32_t
*
)
MAP_FAILED
;
volatile
uint32_t
*
bcm2835_pwm
=
(
volatile
uint32_t
*
)
MAP_FAILED
;
volatile
uint32_t
*
bcm2835_clk
=
(
volatile
uint32_t
*
)
MAP_FAILED
;
volatile
uint32_t
*
bcm2835_pads
=
(
volatile
uint32_t
*
)
MAP_FAILED
;
volatile
uint32_t
*
bcm2835_spi0
=
(
volatile
uint32_t
*
)
MAP_FAILED
;
volatile
uint32_t
*
bcm2835_bsc0
=
(
volatile
uint32_t
*
)
MAP_FAILED
;
volatile
uint32_t
*
bcm2835_bsc1
=
(
volatile
uint32_t
*
)
MAP_FAILED
;
volatile
uint32_t
*
bcm2835_st
=
(
volatile
uint32_t
*
)
MAP_FAILED
;
// Physical address and size of the peripherals block
// May be overridden on RPi2
uint32_t
*
bcm2835_peripherals_base
=
(
uint32_t
*
)
BCM2835_PERI_BASE
;
uint32_t
bcm2835_peripherals_size
=
BCM2835_PERI_SIZE
;
// Virtual memory address of the mapped peripherals block
void
*
bcm2835_peripherals
=
(
uint32_t
*
)
MAP_FAILED
;
// And the register bases within the peripherals block
uint32_t
*
bcm2835_gpio
=
(
uint32_t
*
)
MAP_FAILED
;
uint32_t
*
bcm2835_pwm
=
(
uint32_t
*
)
MAP_FAILED
;
uint32_t
*
bcm2835_clk
=
(
uint32_t
*
)
MAP_FAILED
;
uint32_t
*
bcm2835_pads
=
(
uint32_t
*
)
MAP_FAILED
;
uint32_t
*
bcm2835_spi0
=
(
uint32_t
*
)
MAP_FAILED
;
uint32_t
*
bcm2835_bsc0
=
(
uint32_t
*
)
MAP_FAILED
;
uint32_t
*
bcm2835_bsc1
=
(
uint32_t
*
)
MAP_FAILED
;
uint32_t
*
bcm2835_st
=
(
uint32_t
*
)
MAP_FAILED
;
// This variable allows us to test on hardware other than RPi.
// It prevents access to the kernel memory, and does not do any peripheral access
...
...
@@ -66,13 +73,38 @@ static unsigned long long epoch ;
// Low level register access functions
//
// Function to return the pointers to the hardware register bases
uint32_t
*
bcm2835_regbase
(
uint8_t
regbase
)
{
switch
(
regbase
)
{
case
BCM2835_REGBASE_ST
:
return
(
uint32_t
*
)
bcm2835_st
;
case
BCM2835_REGBASE_GPIO
:
return
(
uint32_t
*
)
bcm2835_gpio
;
case
BCM2835_REGBASE_PWM
:
return
(
uint32_t
*
)
bcm2835_pwm
;
case
BCM2835_REGBASE_CLK
:
return
(
uint32_t
*
)
bcm2835_clk
;
case
BCM2835_REGBASE_PADS
:
return
(
uint32_t
*
)
bcm2835_pads
;
case
BCM2835_REGBASE_SPI0
:
return
(
uint32_t
*
)
bcm2835_spi0
;
case
BCM2835_REGBASE_BSC0
:
return
(
uint32_t
*
)
bcm2835_bsc0
;
case
BCM2835_REGBASE_BSC1
:
return
(
uint32_t
*
)
bcm2835_st
;
}
return
(
uint32_t
*
)
MAP_FAILED
;
}
void
bcm2835_set_debug
(
uint8_t
d
)
{
debug
=
d
;
}
// safe read from peripheral
uint32_t
bcm2835_peri_read
(
volatile
uint32_t
*
paddr
)
uint32_t
bcm2835_peri_read
(
uint32_t
*
paddr
)
{
if
(
debug
)
{
...
...
@@ -90,7 +122,7 @@ uint32_t bcm2835_peri_read(volatile uint32_t* paddr)
}
// read from peripheral without the read barrier
uint32_t
bcm2835_peri_read_nb
(
volatile
uint32_t
*
paddr
)
uint32_t
bcm2835_peri_read_nb
(
uint32_t
*
paddr
)
{
if
(
debug
)
{
...
...
@@ -104,7 +136,7 @@ uint32_t bcm2835_peri_read_nb(volatile uint32_t* paddr)
}
// safe write to peripheral
void
bcm2835_peri_write
(
volatile
uint32_t
*
paddr
,
uint32_t
value
)
void
bcm2835_peri_write
(
uint32_t
*
paddr
,
uint32_t
value
)
{
if
(
debug
)
{
...
...
@@ -120,7 +152,7 @@ void bcm2835_peri_write(volatile uint32_t* paddr, uint32_t value)
}
// write to peripheral without the write barrier
void
bcm2835_peri_write_nb
(
volatile
uint32_t
*
paddr
,
uint32_t
value
)
void
bcm2835_peri_write_nb
(
uint32_t
*
paddr
,
uint32_t
value
)
{
if
(
debug
)
{
...
...
@@ -134,7 +166,7 @@ void bcm2835_peri_write_nb(volatile uint32_t* paddr, uint32_t value)
}
// Set/clear only the bits in value covered by the mask
void
bcm2835_peri_set_bits
(
volatile
uint32_t
*
paddr
,
uint32_t
value
,
uint32_t
mask
)
void
bcm2835_peri_set_bits
(
uint32_t
*
paddr
,
uint32_t
value
,
uint32_t
mask
)
{
uint32_t
v
=
bcm2835_peri_read
(
paddr
);
v
=
(
v
&
~
mask
)
|
(
value
&
mask
);
...
...
@@ -165,7 +197,7 @@ void bcm2835_peri_set_bits(volatile uint32_t* paddr, uint32_t value, uint32_t ma
void
bcm2835_gpio_fsel
(
uint8_t
pin
,
uint8_t
mode
)
{
// Function selects are 10 pins per 32 bit word, 3 bits per pin
volatile
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPFSEL0
/
4
+
(
pin
/
10
);
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPFSEL0
/
4
+
(
pin
/
10
);
uint8_t
shift
=
(
pin
%
10
)
*
3
;
uint32_t
mask
=
BCM2835_GPIO_FSEL_MASK
<<
shift
;
uint32_t
value
=
mode
<<
shift
;
...
...
@@ -175,7 +207,7 @@ void bcm2835_gpio_fsel(uint8_t pin, uint8_t mode)
// Set output pin
void
bcm2835_gpio_set
(
uint8_t
pin
)
{
volatile
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPSET0
/
4
+
pin
/
32
;
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPSET0
/
4
+
pin
/
32
;
uint8_t
shift
=
pin
%
32
;
bcm2835_peri_write
(
paddr
,
1
<<
shift
);
}
...
...
@@ -183,7 +215,7 @@ void bcm2835_gpio_set(uint8_t pin)
// Clear output pin
void
bcm2835_gpio_clr
(
uint8_t
pin
)
{
volatile
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPCLR0
/
4
+
pin
/
32
;
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPCLR0
/
4
+
pin
/
32
;
uint8_t
shift
=
pin
%
32
;
bcm2835_peri_write
(
paddr
,
1
<<
shift
);
}
...
...
@@ -191,21 +223,21 @@ void bcm2835_gpio_clr(uint8_t pin)
// Set all output pins in the mask
void
bcm2835_gpio_set_multi
(
uint32_t
mask
)
{
volatile
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPSET0
/
4
;
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPSET0
/
4
;
bcm2835_peri_write
(
paddr
,
mask
);
}
// Clear all output pins in the mask
void
bcm2835_gpio_clr_multi
(
uint32_t
mask
)
{
volatile
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPCLR0
/
4
;
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPCLR0
/
4
;
bcm2835_peri_write
(
paddr
,
mask
);
}
// Read input pin
uint8_t
bcm2835_gpio_lev
(
uint8_t
pin
)
{
volatile
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPLEV0
/
4
+
pin
/
32
;
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPLEV0
/
4
+
pin
/
32
;
uint8_t
shift
=
pin
%
32
;
uint32_t
value
=
bcm2835_peri_read
(
paddr
);
return
(
value
&
(
1
<<
shift
))
?
HIGH
:
LOW
;
...
...
@@ -215,7 +247,7 @@ uint8_t bcm2835_gpio_lev(uint8_t pin)
// Sigh cant support interrupts yet
uint8_t
bcm2835_gpio_eds
(
uint8_t
pin
)
{
volatile
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPEDS0
/
4
+
pin
/
32
;
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPEDS0
/
4
+
pin
/
32
;
uint8_t
shift
=
pin
%
32
;
uint32_t
value
=
bcm2835_peri_read
(
paddr
);
return
(
value
&
(
1
<<
shift
))
?
HIGH
:
LOW
;
...
...
@@ -224,7 +256,7 @@ uint8_t bcm2835_gpio_eds(uint8_t pin)
// Write a 1 to clear the bit in EDS
void
bcm2835_gpio_set_eds
(
uint8_t
pin
)
{
volatile
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPEDS0
/
4
+
pin
/
32
;
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPEDS0
/
4
+
pin
/
32
;
uint8_t
shift
=
pin
%
32
;
uint32_t
value
=
1
<<
shift
;
bcm2835_peri_write
(
paddr
,
value
);
...
...
@@ -233,14 +265,14 @@ void bcm2835_gpio_set_eds(uint8_t pin)
// Rising edge detect enable
void
bcm2835_gpio_ren
(
uint8_t
pin
)
{
volatile
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPREN0
/
4
+
pin
/
32
;
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPREN0
/
4
+
pin
/
32
;
uint8_t
shift
=
pin
%
32
;
uint32_t
value
=
1
<<
shift
;
bcm2835_peri_set_bits
(
paddr
,
value
,
value
);
}
void
bcm2835_gpio_clr_ren
(
uint8_t
pin
)
{
volatile
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPREN0
/
4
+
pin
/
32
;
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPREN0
/
4
+
pin
/
32
;
uint8_t
shift
=
pin
%
32
;
uint32_t
value
=
1
<<
shift
;
bcm2835_peri_set_bits
(
paddr
,
0
,
value
);
...
...
@@ -249,14 +281,14 @@ void bcm2835_gpio_clr_ren(uint8_t pin)
// Falling edge detect enable
void
bcm2835_gpio_fen
(
uint8_t
pin
)
{
volatile
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPFEN0
/
4
+
pin
/
32
;
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPFEN0
/
4
+
pin
/
32
;
uint8_t
shift
=
pin
%
32
;
uint32_t
value
=
1
<<
shift
;
bcm2835_peri_set_bits
(
paddr
,
value
,
value
);
}
void
bcm2835_gpio_clr_fen
(
uint8_t
pin
)
{
volatile
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPFEN0
/
4
+
pin
/
32
;
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPFEN0
/
4
+
pin
/
32
;
uint8_t
shift
=
pin
%
32
;
uint32_t
value
=
1
<<
shift
;
bcm2835_peri_set_bits
(
paddr
,
0
,
value
);
...
...
@@ -265,14 +297,14 @@ void bcm2835_gpio_clr_fen(uint8_t pin)
// High detect enable
void
bcm2835_gpio_hen
(
uint8_t
pin
)
{
volatile
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPHEN0
/
4
+
pin
/
32
;
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPHEN0
/
4
+
pin
/
32
;
uint8_t
shift
=
pin
%
32
;
uint32_t
value
=
1
<<
shift
;
bcm2835_peri_set_bits
(
paddr
,
value
,
value
);
}
void
bcm2835_gpio_clr_hen
(
uint8_t
pin
)
{
volatile
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPHEN0
/
4
+
pin
/
32
;
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPHEN0
/
4
+
pin
/
32
;
uint8_t
shift
=
pin
%
32
;
uint32_t
value
=
1
<<
shift
;
bcm2835_peri_set_bits
(
paddr
,
0
,
value
);
...
...
@@ -281,14 +313,14 @@ void bcm2835_gpio_clr_hen(uint8_t pin)
// Low detect enable
void
bcm2835_gpio_len
(
uint8_t
pin
)
{
volatile
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPLEN0
/
4
+
pin
/
32
;
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPLEN0
/
4
+
pin
/
32
;
uint8_t
shift
=
pin
%
32
;
uint32_t
value
=
1
<<
shift
;
bcm2835_peri_set_bits
(
paddr
,
value
,
value
);
}
void
bcm2835_gpio_clr_len
(
uint8_t
pin
)
{
volatile
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPLEN0
/
4
+
pin
/
32
;
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPLEN0
/
4
+
pin
/
32
;
uint8_t
shift
=
pin
%
32
;
uint32_t
value
=
1
<<
shift
;
bcm2835_peri_set_bits
(
paddr
,
0
,
value
);
...
...
@@ -297,14 +329,14 @@ void bcm2835_gpio_clr_len(uint8_t pin)
// Async rising edge detect enable
void
bcm2835_gpio_aren
(
uint8_t
pin
)
{
volatile
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPAREN0
/
4
+
pin
/
32
;
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPAREN0
/
4
+
pin
/
32
;
uint8_t
shift
=
pin
%
32
;
uint32_t
value
=
1
<<
shift
;
bcm2835_peri_set_bits
(
paddr
,
value
,
value
);
}
void
bcm2835_gpio_clr_aren
(
uint8_t
pin
)
{
volatile
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPAREN0
/
4
+
pin
/
32
;
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPAREN0
/
4
+
pin
/
32
;
uint8_t
shift
=
pin
%
32
;
uint32_t
value
=
1
<<
shift
;
bcm2835_peri_set_bits
(
paddr
,
0
,
value
);
...
...
@@ -313,14 +345,14 @@ void bcm2835_gpio_clr_aren(uint8_t pin)
// Async falling edge detect enable
void
bcm2835_gpio_afen
(
uint8_t
pin
)
{
volatile
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPAFEN0
/
4
+
pin
/
32
;
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPAFEN0
/
4
+
pin
/
32
;
uint8_t
shift
=
pin
%
32
;
uint32_t
value
=
1
<<
shift
;
bcm2835_peri_set_bits
(
paddr
,
value
,
value
);
}
void
bcm2835_gpio_clr_afen
(
uint8_t
pin
)
{
volatile
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPAFEN0
/
4
+
pin
/
32
;
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPAFEN0
/
4
+
pin
/
32
;
uint8_t
shift
=
pin
%
32
;
uint32_t
value
=
1
<<
shift
;
bcm2835_peri_set_bits
(
paddr
,
0
,
value
);
...
...
@@ -329,7 +361,7 @@ void bcm2835_gpio_clr_afen(uint8_t pin)
// Set pullup/down
void
bcm2835_gpio_pud
(
uint8_t
pud
)
{
volatile
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPPUD
/
4
;
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPPUD
/
4
;
bcm2835_peri_write
(
paddr
,
pud
);
}
...
...
@@ -337,7 +369,7 @@ void bcm2835_gpio_pud(uint8_t pud)
// Clocks the value of pud into the GPIO pin
void
bcm2835_gpio_pudclk
(
uint8_t
pin
,
uint8_t
on
)
{
volatile
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPPUDCLK0
/
4
+
pin
/
32
;
uint32_t
*
paddr
=
bcm2835_gpio
+
BCM2835_GPPUDCLK0
/
4
+
pin
/
32
;
uint8_t
shift
=
pin
%
32
;
bcm2835_peri_write
(
paddr
,
(
on
?
1
:
0
)
<<
shift
);
}
...
...
@@ -345,7 +377,7 @@ void bcm2835_gpio_pudclk(uint8_t pin, uint8_t on)
// Read GPIO pad behaviour for groups of GPIOs
uint32_t
bcm2835_gpio_pad
(
uint8_t
group
)
{
volatile
uint32_t
*
paddr
=
bcm2835_pads
+
BCM2835_PADS_GPIO_0_27
/
4
+
group
*
2
;
uint32_t
*
paddr
=
bcm2835_pads
+
BCM2835_PADS_GPIO_0_27
/
4
+
group
*
2
;
return
bcm2835_peri_read
(
paddr
);
}
...
...
@@ -354,7 +386,7 @@ uint32_t bcm2835_gpio_pad(uint8_t group)
// BCM2835_PAD_SLEW_RATE_UNLIMITED | BCM2835_PAD_HYSTERESIS_ENABLED | BCM2835_PAD_DRIVE_8mA
void
bcm2835_gpio_set_pad
(
uint8_t
group
,
uint32_t
control
)
{
volatile
uint32_t
*
paddr
=
bcm2835_pads
+
BCM2835_PADS_GPIO_0_27
/
4
+
group
*
2
;
uint32_t
*
paddr
=
bcm2835_pads
+
BCM2835_PADS_GPIO_0_27
/
4
+
group
*
2
;
bcm2835_peri_write
(
paddr
,
control
|
BCM2835_PAD_PASSWRD
);
}
...
...
@@ -461,18 +493,14 @@ void bcm2835_gpio_set_pud(uint8_t pin, uint8_t pud)
void
bcm2835_spi_begin
(
void
)
{
// 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
// Enable CE0 by default, will be disabled if bcm2835_chipSelect() is called using another pin
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
;
uint32_t
*
paddr
=
bcm2835_spi0
+
BCM2835_SPI0_CS
/
4
;
bcm2835_peri_write
(
paddr
,
0
);
// All 0s
// Clear TX and RX fifos
...
...
@@ -500,13 +528,13 @@ void bcm2835_spi_setBitOrder(uint8_t order)
// of the APB clock
void
bcm2835_spi_setClockDivider
(
uint16_t
divider
)
{
volatile
uint32_t
*
paddr
=
bcm2835_spi0
+
BCM2835_SPI0_CLK
/
4
;
uint32_t
*
paddr
=
bcm2835_spi0
+
BCM2835_SPI0_CLK
/
4
;
bcm2835_peri_write
(
paddr
,
divider
);
}
void
bcm2835_spi_setDataMode
(
uint8_t
mode
)
{
volatile
uint32_t
*
paddr
=
bcm2835_spi0
+
BCM2835_SPI0_CS
/
4
;
uint32_t
*
paddr
=
bcm2835_spi0
+
BCM2835_SPI0_CS
/
4
;
// Mask in the CPO and CPHA bits of CS
bcm2835_peri_set_bits
(
paddr
,
mode
<<
2
,
BCM2835_SPI0_CS_CPOL
|
BCM2835_SPI0_CS_CPHA
);
}
...
...
@@ -514,8 +542,8 @@ void bcm2835_spi_setDataMode(uint8_t mode)
// Writes (and reads) a single byte to SPI
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
;
uint32_t
*
paddr
=
bcm2835_spi0
+
BCM2835_SPI0_CS
/
4
;
uint32_t
*
fifo
=
bcm2835_spi0
+
BCM2835_SPI0_FIFO
/
4
;
// This is Polled transfer as per section 10.6.1
// BUG ALERT: what happens if we get interupted in this section, and someone else
...
...
@@ -549,8 +577,8 @@ uint8_t bcm2835_spi_transfer(uint8_t value)
// Writes (and reads) an number of bytes to SPI
void
bcm2835_spi_transfernb
(
char
*
tbuf
,
char
*
rbuf
,
uint32_t
len
)
{
volatile
uint32_t
*
paddr
=
bcm2835_spi0
+
BCM2835_SPI0_CS
/
4
;
volatile
uint32_t
*
fifo
=
bcm2835_spi0
+
BCM2835_SPI0_FIFO
/
4
;
uint32_t
*
paddr
=
bcm2835_spi0
+
BCM2835_SPI0_CS
/
4
;
uint32_t
*
fifo
=
bcm2835_spi0
+
BCM2835_SPI0_FIFO
/
4
;
uint32_t
TXCnt
=
0
;
uint32_t
RXCnt
=
0
;
...
...
@@ -568,7 +596,7 @@ void bcm2835_spi_transfernb(char* tbuf, char* rbuf, uint32_t len)
while
((
TXCnt
<
len
)
||
(
RXCnt
<
len
))
{
// TX fifo not full, so add some more bytes
while
(
(
bcm2835_peri_read
(
paddr
)
&
BCM2835_SPI0_CS_TXD
)
&&
(
TXCnt
<
len
)
&&
!
(
bcm2835_peri_read
(
paddr
)
&
BCM2835_SPI0_CS_RXR
)
)
while
(
((
bcm2835_peri_read
(
paddr
)
&
BCM2835_SPI0_CS_TXD
))
&&
(
TXCnt
<
len
)
)
{
bcm2835_peri_write_nb
(
fifo
,
tbuf
[
TXCnt
]);
TXCnt
++
;
...
...
@@ -580,18 +608,19 @@ void bcm2835_spi_transfernb(char* tbuf, char* rbuf, uint32_t len)
RXCnt
++
;
}
}
while
(
!
(
bcm2835_peri_read
(
paddr
)
&
BCM2835_SPI0_CS_DONE
)
)
;
if
(
TXCnt
==
len
)
bcm2835_peri_set_bits
(
paddr
,
0
,
BCM2835_SPI0_CS_TA
)
// Wait for DONE to be set
while
(
!
(
bcm2835_peri_read_nb
(
paddr
)
&
BCM2835_SPI0_CS_DONE
))
;
}
// Set TA = 0, and also set the barrier
bcm2835_peri_set_bits
(
paddr
,
0
,
BCM2835_SPI0_CS_TA
);
}
// Writes an number of bytes to SPI
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
;
uint32_t
*
paddr
=
bcm2835_spi0
+
BCM2835_SPI0_CS
/
4
;
uint32_t
*
fifo
=
bcm2835_spi0
+
BCM2835_SPI0_FIFO
/
4
;
// This is Polled transfer as per section 10.6.1
// BUG ALERT: what happens if we get interupted in this section, and someone else
...
...
@@ -637,22 +666,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
}
uint32_t
*
paddr
=
bcm2835_spi0
+
BCM2835_SPI0_CS
/
4
;
// Mask in the CS bits of CS
bcm2835_peri_set_bits
(
paddr
,
cs
,
BCM2835_SPI0_CS_CS
);
}
void
bcm2835_spi_setChipSelectPolarity
(
uint8_t
cs
,
uint8_t
active
)
{
volatile
uint32_t
*
paddr
=
bcm2835_spi0
+
BCM2835_SPI0_CS
/
4
;
uint32_t
*
paddr
=
bcm2835_spi0
+
BCM2835_SPI0_CS
/
4
;
uint8_t
shift
=
21
+
cs
;
// Mask in the appropriate CSPOLn bit
bcm2835_peri_set_bits
(
paddr
,
active
<<
shift
,
1
<<
shift
);
...
...
@@ -661,12 +682,12 @@ void bcm2835_spi_setChipSelectPolarity(uint8_t cs, uint8_t active)
void
bcm2835_i2c_begin
(
void
)
{
#ifdef I2C_V1
volatile
uint32_t
*
paddr
=
bcm2835_bsc0
+
BCM2835_BSC_DIV
/
4
;
uint32_t
*
paddr
=
bcm2835_bsc0
+
BCM2835_BSC_DIV
/
4
;
// Set the I2C/BSC0 pins to the Alt 0 function to enable I2C access on them
bcm2835_gpio_fsel
(
RPI_GPIO_P1_03
,
BCM2835_GPIO_FSEL_ALT0
);
// SDA
bcm2835_gpio_fsel
(
RPI_GPIO_P1_05
,
BCM2835_GPIO_FSEL_ALT0
);
// SCL
#else
volatile
uint32_t
*
paddr
=
bcm2835_bsc1
+
BCM2835_BSC_DIV
/
4
;
uint32_t
*
paddr
=
bcm2835_bsc1
+
BCM2835_BSC_DIV
/
4
;
// 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
...
...
@@ -697,9 +718,9 @@ void bcm2835_i2c_setSlaveAddress(uint8_t addr)
{
// Set I2C Device Address
#ifdef I2C_V1
volatile
uint32_t
*
paddr
=
bcm2835_bsc0
+
BCM2835_BSC_A
/
4
;
uint32_t
*
paddr
=
bcm2835_bsc0
+
BCM2835_BSC_A
/
4
;
#else
volatile
uint32_t
*
paddr
=
bcm2835_bsc1
+
BCM2835_BSC_A
/
4
;
uint32_t
*
paddr
=
bcm2835_bsc1
+
BCM2835_BSC_A
/
4
;
#endif
bcm2835_peri_write
(
paddr
,
addr
);
}
...
...
@@ -710,9 +731,9 @@ void bcm2835_i2c_setSlaveAddress(uint8_t addr)
void
bcm2835_i2c_setClockDivider
(
uint16_t
divider
)
{
#ifdef I2C_V1
volatile
uint32_t
*
paddr
=
bcm2835_bsc0
+
BCM2835_BSC_DIV
/
4
;
uint32_t
*
paddr
=
bcm2835_bsc0
+
BCM2835_BSC_DIV
/
4
;
#else
volatile
uint32_t
*
paddr
=
bcm2835_bsc1
+
BCM2835_BSC_DIV
/
4
;
uint32_t
*
paddr
=
bcm2835_bsc1
+
BCM2835_BSC_DIV
/
4
;
#endif
bcm2835_peri_write
(
paddr
,
divider
);
// Calculate time for transmitting one byte
...
...
@@ -734,15 +755,15 @@ void bcm2835_i2c_set_baudrate(uint32_t baudrate)
uint8_t
bcm2835_i2c_write
(
const
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
;
volatile
uint32_t
*
status
=
bcm2835_bsc0
+
BCM2835_BSC_S
/
4
;
volatile
uint32_t
*
control
=
bcm2835_bsc0
+
BCM2835_BSC_C
/
4
;
uint32_t
*
dlen
=
bcm2835_bsc0
+
BCM2835_BSC_DLEN
/
4
;
uint32_t
*
fifo
=
bcm2835_bsc0
+
BCM2835_BSC_FIFO
/
4
;
uint32_t
*
status
=
bcm2835_bsc0
+
BCM2835_BSC_S
/
4
;
uint32_t
*
control
=
bcm2835_bsc0
+
BCM2835_BSC_C
/
4
;
#else
volatile
uint32_t
*
dlen
=
bcm2835_bsc1
+
BCM2835_BSC_DLEN
/
4
;
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
;
uint32_t
*
dlen
=
bcm2835_bsc1
+
BCM2835_BSC_DLEN
/
4
;
uint32_t
*
fifo
=
bcm2835_bsc1
+
BCM2835_BSC_FIFO
/
4
;
uint32_t
*
status
=
bcm2835_bsc1
+
BCM2835_BSC_S
/
4
;
uint32_t
*
control
=
bcm2835_bsc1
+
BCM2835_BSC_C
/
4
;
#endif
uint32_t
remaining
=
len
;
...
...
@@ -805,15 +826,15 @@ uint8_t bcm2835_i2c_write(const char * buf, uint32_t len)
uint8_t
bcm2835_i2c_read
(
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
;
volatile
uint32_t
*
status
=
bcm2835_bsc0
+
BCM2835_BSC_S
/
4
;
volatile
uint32_t
*
control
=
bcm2835_bsc0
+
BCM2835_BSC_C
/
4
;
uint32_t
*
dlen
=
bcm2835_bsc0
+
BCM2835_BSC_DLEN
/
4
;
uint32_t
*
fifo
=
bcm2835_bsc0
+
BCM2835_BSC_FIFO
/
4
;
uint32_t
*
status
=
bcm2835_bsc0
+
BCM2835_BSC_S
/
4
;
uint32_t
*
control
=
bcm2835_bsc0
+
BCM2835_BSC_C
/
4
;
#else
volatile
uint32_t
*
dlen
=
bcm2835_bsc1
+
BCM2835_BSC_DLEN
/
4
;
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
;
uint32_t
*
dlen
=
bcm2835_bsc1
+
BCM2835_BSC_DLEN
/
4
;
uint32_t
*
fifo
=
bcm2835_bsc1
+
BCM2835_BSC_FIFO
/
4
;
uint32_t
*
status
=
bcm2835_bsc1
+
BCM2835_BSC_S
/
4
;
uint32_t
*
control
=
bcm2835_bsc1
+
BCM2835_BSC_C
/
4
;
#endif
uint32_t
remaining
=
len
;
...
...
@@ -879,15 +900,15 @@ uint8_t bcm2835_i2c_read(char* buf, uint32_t len)
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
;
volatile
uint32_t
*
status
=
bcm2835_bsc0
+
BCM2835_BSC_S
/
4
;
volatile
uint32_t
*
control
=
bcm2835_bsc0
+
BCM2835_BSC_C
/
4
;
uint32_t
*
dlen
=
bcm2835_bsc0
+
BCM2835_BSC_DLEN
/
4
;
uint32_t
*
fifo
=
bcm2835_bsc0
+
BCM2835_BSC_FIFO
/
4
;
uint32_t
*
status
=
bcm2835_bsc0
+
BCM2835_BSC_S
/
4
;
uint32_t
*
control
=
bcm2835_bsc0
+
BCM2835_BSC_C
/
4
;
#else
volatile
uint32_t
*
dlen
=
bcm2835_bsc1
+
BCM2835_BSC_DLEN
/
4
;
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
;
uint32_t
*
dlen
=
bcm2835_bsc1
+
BCM2835_BSC_DLEN
/
4
;
uint32_t
*
fifo
=
bcm2835_bsc1
+
BCM2835_BSC_FIFO
/
4
;
uint32_t
*
status
=
bcm2835_bsc1
+
BCM2835_BSC_S
/
4
;
uint32_t
*
control
=
bcm2835_bsc1
+
BCM2835_BSC_C
/
4
;
#endif
uint32_t
remaining
=
len
;
uint32_t
i
=
0
;
...
...
@@ -969,15 +990,15 @@ uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len)
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
;
volatile
uint32_t
*
status
=
bcm2835_bsc0
+
BCM2835_BSC_S
/
4
;
volatile
uint32_t
*
control
=
bcm2835_bsc0
+
BCM2835_BSC_C
/
4
;
uint32_t
*
dlen
=
bcm2835_bsc0
+
BCM2835_BSC_DLEN
/
4
;
uint32_t
*
fifo
=
bcm2835_bsc0
+
BCM2835_BSC_FIFO
/
4
;
uint32_t
*
status
=
bcm2835_bsc0
+
BCM2835_BSC_S
/
4
;
uint32_t
*
control
=
bcm2835_bsc0
+
BCM2835_BSC_C
/
4
;
#else
volatile
uint32_t
*
dlen
=
bcm2835_bsc1
+
BCM2835_BSC_DLEN
/
4
;
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
;
uint32_t
*
dlen
=
bcm2835_bsc1
+
BCM2835_BSC_DLEN
/
4
;
uint32_t
*
fifo
=
bcm2835_bsc1
+
BCM2835_BSC_FIFO
/
4
;
uint32_t
*
status
=
bcm2835_bsc1
+
BCM2835_BSC_S
/
4
;
uint32_t
*
control
=
bcm2835_bsc1
+
BCM2835_BSC_C
/
4
;
#endif
uint32_t
remaining
=
cmds_len
;
...
...
@@ -1070,7 +1091,7 @@ uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint
// Read the System Timer Counter (64-bits)
uint64_t
bcm2835_st_read
(
void
)
{
volatile
uint32_t
*
paddr
;
uint32_t
*
paddr
;
uint32_t
hi
,
lo
;
uint64_t
st
;
paddr
=
bcm2835_st
+
BCM2835_ST_CHI
/
4
;
...
...
@@ -1186,7 +1207,7 @@ void *malloc_aligned(size_t size)
static
void
*
mapmem
(
const
char
*
msg
,
size_t
size
,
int
fd
,
off_t
off
)
{
void
*
map
=
mmap
(
NULL
,
size
,
(
PROT_READ
|
PROT_WRITE
),
MAP_SHARED
,
fd
,
off
);
if
(
MAP_FAILED
==
map
)
if
(
map
==
MAP_FAILED
)
fprintf
(
stderr
,
"bcm2835_init: %s mmap failed: %s
\n
"
,
msg
,
strerror
(
errno
));
return
map
;
}
...
...
@@ -1200,21 +1221,40 @@ static void unmapmem(void **pmem, size_t size)
// Initialise this library.
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
;
bcm2835_gpio
=
(
uint32_t
*
)
BCM2835_GPIO_BASE
;
bcm2835_pwm
=
(
uint32_t
*
)
BCM2835_GPIO_PWM
;
bcm2835_spi0
=
(
uint32_t
*
)
BCM2835_SPI0_BASE
;
bcm2835_bsc0
=
(
uint32_t
*
)
BCM2835_BSC0_BASE
;
bcm2835_bsc1
=
(
uint32_t
*
)
BCM2835_BSC1_BASE
;
bcm2835_st
=
(
uint32_t
*
)
BCM2835_ST_BASE
;
bcm2835_peripherals
=
(
uint32_t
*
)
BCM2835_PERI_BASE
;
bcm2835_pads
=
bcm2835_peripherals
+
BCM2835_GPIO_PADS
;
bcm2835_clk
=
bcm2835_peripherals
+
BCM2835_CLOCK_BASE
;
bcm2835_gpio
=
bcm2835_peripherals
+
BCM2835_GPIO_BASE
;
bcm2835_pwm
=
bcm2835_peripherals
+
BCM2835_GPIO_PWM
;
bcm2835_spi0
=
bcm2835_peripherals
+
BCM2835_SPI0_BASE
;
bcm2835_bsc0
=
bcm2835_peripherals
+
BCM2835_BSC0_BASE
;
bcm2835_bsc1
=
bcm2835_peripherals
+
BCM2835_BSC1_BASE
;
bcm2835_st
=
bcm2835_peripherals
+
BCM2835_ST_BASE
;
return
1
;
// Success
}
// Figure out the base and size of the peripheral address block, based on whether we are on a RPI2 or not,
// using the device-tree
FILE
*
fp
=
fopen
(
BMC2835_RPI2_DT_FILENAME
,
"rb"
);
if
(
fp
)
{
unsigned
char
buf
[
4
];
fseek
(
fp
,
BMC2835_RPI2_DT_PERI_BASE_ADDRESS_OFFSET
,
SEEK_SET
);
if
(
fread
(
buf
,
1
,
sizeof
(
buf
),
fp
)
==
sizeof
(
buf
))
bcm2835_peripherals_base
=
(
uint32_t
*
)(
buf
[
0
]
<<
24
|
buf
[
1
]
<<
16
|
buf
[
2
]
<<
8
|
buf
[
3
]
<<
0
);
fseek
(
fp
,
BMC2835_RPI2_DT_PERI_SIZE_OFFSET
,
SEEK_SET
);
if
(
fread
(
buf
,
1
,
sizeof
(
buf
),
fp
)
==
sizeof
(
buf
))
bcm2835_peripherals_size
=
(
buf
[
0
]
<<
24
|
buf
[
1
]
<<
16
|
buf
[
2
]
<<
8
|
buf
[
3
]
<<
0
);
fclose
(
fp
);
}
// else we are prob on RPi 1 with BCM2835, and use the hardwired defaults
// Now get ready to map the peripherals block
int
memfd
=
-
1
;
int
ok
=
0
;
// Open the master /dev/memory device
...
...
@@ -1225,34 +1265,19 @@ int bcm2835_init(void)
goto
exit
;
}
// GPIO:
bcm2835_gpio
=
(
volatile
uint32_t
*
)
mapmem
(
"gpio"
,
BCM2835_BLOCK_SIZE
,
memfd
,
BCM2835_GPIO_BASE
);
if
(
bcm2835_gpio
==
MAP_FAILED
)
goto
exit
;
// PWM
bcm2835_pwm
=
(
volatile
uint32_t
*
)
mapmem
(
"pwm"
,
BCM2835_BLOCK_SIZE
,
memfd
,
BCM2835_GPIO_PWM
);
if
(
bcm2835_pwm
==
MAP_FAILED
)
goto
exit
;
// 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
;
// I2C
bcm2835_bsc0
=
(
volatile
uint32_t
*
)
mapmem
(
"bsc0"
,
BCM2835_BLOCK_SIZE
,
memfd
,
BCM2835_BSC0_BASE
);
if
(
bcm2835_bsc0
==
MAP_FAILED
)
goto
exit
;
bcm2835_bsc1
=
(
volatile
uint32_t
*
)
mapmem
(
"bsc1"
,
BCM2835_BLOCK_SIZE
,
memfd
,
BCM2835_BSC1_BASE
);
if
(
bcm2835_bsc1
==
MAP_FAILED
)
goto
exit
;
// ST
bcm2835_st
=
(
volatile
uint32_t
*
)
mapmem
(
"st"
,
BCM2835_BLOCK_SIZE
,
memfd
,
BCM2835_ST_BASE
);
if
(
bcm2835_st
==
MAP_FAILED
)
goto
exit
;
// Base of the peripherals block is mapped to VM
bcm2835_peripherals
=
(
uint32_t
*
)
mapmem
(
"gpio"
,
bcm2835_peripherals_size
,
memfd
,
(
uint32_t
)
bcm2835_peripherals_base
);
if
(
bcm2835_peripherals
==
MAP_FAILED
)
goto
exit
;
// Now compute the base addresses of various peripherals, which are at fixed offsets within the mapped peripherals block
bcm2835_gpio
=
bcm2835_peripherals
+
BCM2835_GPIO_BASE
;
bcm2835_pwm
=
bcm2835_peripherals
+
BCM2835_GPIO_PWM
;
bcm2835_clk
=
bcm2835_peripherals
+
BCM2835_CLOCK_BASE
;
bcm2835_pads
=
bcm2835_peripherals
+
BCM2835_GPIO_PADS
;
bcm2835_spi0
=
bcm2835_peripherals
+
BCM2835_SPI0_BASE
;
bcm2835_bsc0
=
bcm2835_peripherals
+
BCM2835_BSC0_BASE
;
// I2C
bcm2835_bsc1
=
bcm2835_peripherals
+
BCM2835_BSC1_BASE
;
// I2C
bcm2835_st
=
bcm2835_peripherals
+
BCM2835_ST_BASE
;
ok
=
1
;
...
...
@@ -1273,14 +1298,17 @@ exit:
int
bcm2835_close
(
void
)
{
if
(
debug
)
return
1
;
// Success
unmapmem
((
void
**
)
&
bcm2835_gpio
,
BCM2835_BLOCK_SIZE
);
unmapmem
((
void
**
)
&
bcm2835_pwm
,
BCM2835_BLOCK_SIZE
);
unmapmem
((
void
**
)
&
bcm2835_clk
,
BCM2835_BLOCK_SIZE
);
unmapmem
((
void
**
)
&
bcm2835_spi0
,
BCM2835_BLOCK_SIZE
);
unmapmem
((
void
**
)
&
bcm2835_bsc0
,
BCM2835_BLOCK_SIZE
);
unmapmem
((
void
**
)
&
bcm2835_bsc1
,
BCM2835_BLOCK_SIZE
);
unmapmem
((
void
**
)
&
bcm2835_st
,
BCM2835_BLOCK_SIZE
);
unmapmem
((
void
**
)
&
bcm2835_pads
,
BCM2835_BLOCK_SIZE
);
unmapmem
((
void
**
)
&
bcm2835_peripherals
,
bcm2835_peripherals_size
);
bcm2835_peripherals
=
MAP_FAILED
;
bcm2835_gpio
=
MAP_FAILED
;
bcm2835_pwm
=
MAP_FAILED
;
bcm2835_clk
=
MAP_FAILED
;
bcm2835_pads
=
MAP_FAILED
;
bcm2835_spi0
=
MAP_FAILED
;
bcm2835_bsc0
=
MAP_FAILED
;
bcm2835_bsc1
=
MAP_FAILED
;
bcm2835_st
=
MAP_FAILED
;
return
1
;
// Success
}
...
...
RPi/bcm2835.h
View file @
f06ca7cb
...
...
@@ -29,7 +29,7 @@
/// BCM 2835).
///
/// The version of the package that this documentation refers to can be downloaded
/// from http://www.airspayce.com/mikem/bcm2835/bcm2835-1.3
6
.tar.gz
/// from http://www.airspayce.com/mikem/bcm2835/bcm2835-1.3
9
.tar.gz
/// You can find the latest version at http://www.airspayce.com/mikem/bcm2835
///
/// Several example programs are provided.
...
...
@@ -316,6 +316,12 @@
/// \version 1.37 Moved confiure.in to configure.ac as receommnded by autoreconf.<br>
/// Improvements to bcm2835_st_read to account for possible timer overflow, contributed by 'Ed'.<br>
/// Added definitions for Raspberry Pi B+ J8 header GPIO pins.<br>
/// \version 1.38 Added bcm2835_regbase for the benefit of C# wrappers, patch by Frank Hommers <br>
/// \version 1.39 Beta version of RPi2 compatibility. Not tested here on RPi2 hardware.
/// Testers please confirm correct operation on RPi2.<br>
/// Unneccessary 'volatile' qualifiers removed from all variables and signatures.<br>
/// Removed unsupportable PWM dividers, based on a report from Christophe Cecillon.<br>
/// Minor improvements to spi.c example.<br>
///
/// \author Mike McCauley (mikem@airspayce.com) DO NOT CONTACT THE AUTHOR DIRECTLY: USE THE LISTS
...
...
@@ -340,58 +346,92 @@
/// Speed of the core clock core_clk
#define BCM2835_CORE_CLK_HZ 250000000 ///< 250 MHz
// Physical addresses for various peripheral register sets
/// On RPi2 with BCM2836, the base of the peripherals is read from a /proc file
#define BMC2835_RPI2_DT_FILENAME "/proc/device-tree/soc/ranges"
/// On RPi2, offset into BMC2835_RPI2_DT_FILENAME for the peripherals base address
#define BMC2835_RPI2_DT_PERI_BASE_ADDRESS_OFFSET 4
/// On RPi2, offset into BMC2835_RPI2_DT_FILENAME for the peripherals size address
#define BMC2835_RPI2_DT_PERI_SIZE_OFFSET 8
/// Physical addresses for various peripheral register sets
/// Base Physical Address of the BCM 2835 peripheral registers
/// Note this is different for the RPi2 BCM2836, where this isderived from /proc/device-tree/soc/ranges
#define BCM2835_PERI_BASE 0x20000000
/// Base Physical Address of the System Timer registers
#define BCM2835_ST_BASE (BCM2835_PERI_BASE + 0x3000)
/// Base Physical Address of the Pads registers
#define BCM2835_GPIO_PADS (BCM2835_PERI_BASE + 0x100000)
/// Base Physical Address of the Clock/timer registers
#define BCM2835_CLOCK_BASE (BCM2835_PERI_BASE + 0x101000)
/// Base Physical Address of the GPIO registers
#define BCM2835_GPIO_BASE (BCM2835_PERI_BASE + 0x200000)
/// Base Physical Address of the SPI0 registers
#define BCM2835_SPI0_BASE (BCM2835_PERI_BASE + 0x204000)
/// Base Physical Address of the BSC0 registers
#define BCM2835_BSC0_BASE (BCM2835_PERI_BASE + 0x205000)
/// Base Physical Address of the PWM registers
#define BCM2835_GPIO_PWM (BCM2835_PERI_BASE + 0x20C000)
/// Base Physical Address of the BSC1 registers
#define BCM2835_BSC1_BASE (BCM2835_PERI_BASE + 0x804000)
/// Size of the perioherals block on RPi 1
#define BCM2835_PERI_SIZE 0x01000000
/// Offsets for the bases of various peripherals within the peripherals block
/// Base Address of the System Timer registers
#define BCM2835_ST_BASE 0x3000
/// Base Address of the Pads registers
#define BCM2835_GPIO_PADS 0x100000
/// Base Address of the Clock/timer registers
#define BCM2835_CLOCK_BASE 0x101000
/// Base Address of the GPIO registers
#define BCM2835_GPIO_BASE 0x200000
/// Base Address of the SPI0 registers
#define BCM2835_SPI0_BASE 0x204000
/// Base Address of the BSC0 registers
#define BCM2835_BSC0_BASE 0x205000
/// Base Address of the PWM registers
#define BCM2835_GPIO_PWM 0x20C000
/// Base Address of the BSC1 registers
#define BCM2835_BSC1_BASE 0x804000
/// Physical address and size of the peripherals block
/// May be overridden on RPi2
extern
uint32_t
*
bcm2835_peripherals_base
;
/// Size of the peripherals block to be mapped
extern
uint32_t
bcm2835_peripherals_size
;
/// Virtual memory address of the mapped peripherals block
extern
void
*
bcm2835_peripherals
;
/// Base of the ST (System Timer) registers.
/// Available after bcm2835_init has been called
extern
volatile
uint32_t
*
bcm2835_st
;
extern
uint32_t
*
bcm2835_st
;
/// Base of the GPIO registers.
/// Available after bcm2835_init has been called
extern
volatile
uint32_t
*
bcm2835_gpio
;
extern
uint32_t
*
bcm2835_gpio
;
/// Base of the PWM registers.
/// Available after bcm2835_init has been called
extern
volatile
uint32_t
*
bcm2835_pwm
;
extern
uint32_t
*
bcm2835_pwm
;
/// Base of the CLK registers.
/// Available after bcm2835_init has been called
extern
volatile
uint32_t
*
bcm2835_clk
;
extern
uint32_t
*
bcm2835_clk
;
/// Base of the PADS registers.
/// Available after bcm2835_init has been called
extern
volatile
uint32_t
*
bcm2835_pads
;
extern
uint32_t
*
bcm2835_pads
;
/// Base of the SPI0 registers.
/// Available after bcm2835_init has been called
extern
volatile
uint32_t
*
bcm2835_spi0
;
extern
uint32_t
*
bcm2835_spi0
;
/// Base of the BSC0 registers.
/// Available after bcm2835_init has been called
extern
volatile
uint32_t
*
bcm2835_bsc0
;
extern
uint32_t
*
bcm2835_bsc0
;
/// Base of the BSC1 registers.
/// Available after bcm2835_init has been called
extern
volatile
uint32_t
*
bcm2835_bsc1
;
extern
uint32_t
*
bcm2835_bsc1
;
/// \brief bcm2835RegisterBase
/// Register bases for bcm2835_regbase()
typedef
enum
{
BCM2835_REGBASE_ST
=
1
,
///< Base of the ST (System Timer) registers.
BCM2835_REGBASE_GPIO
=
2
,
///< Base of the GPIO registers.
BCM2835_REGBASE_PWM
=
3
,
///< Base of the PWM registers.
BCM2835_REGBASE_CLK
=
4
,
///< Base of the CLK registers.
BCM2835_REGBASE_PADS
=
5
,
///< Base of the PADS registers.
BCM2835_REGBASE_SPI0
=
6
,
///< Base of the SPI0 registers.
BCM2835_REGBASE_BSC0
=
7
,
///< Base of the BSC0 registers.
BCM2835_REGBASE_BSC1
=
8
///< Base of the BSC1 registers.
}
bcm2835RegisterBase
;
/// Size of memory page on RPi
#define BCM2835_PAGE_SIZE (4*1024)
...
...
@@ -437,24 +477,24 @@ extern volatile uint32_t *bcm2835_bsc1;
/// Port function select modes for bcm2835_gpio_fsel()
typedef
enum
{
BCM2835_GPIO_FSEL_INPT
=
0
x
00
,
///< Input
BCM2835_GPIO_FSEL_OUTP
=
0
x
01
,
///< Output
BCM2835_GPIO_FSEL_ALT0
=
0
x04
,
///< Alternate function 0
BCM2835_GPIO_FSEL_ALT1
=
0
x05
,
///< Alternate function 1
BCM2835_GPIO_FSEL_ALT2
=
0
x06
,
///< Alternate function 2
BCM2835_GPIO_FSEL_ALT3
=
0
x07
,
///< Alternate function 3
BCM2835_GPIO_FSEL_ALT4
=
0
x03
,
///< Alternate function 4
BCM2835_GPIO_FSEL_ALT5
=
0
x02
,
///< Alternate function 5
BCM2835_GPIO_FSEL_MASK
=
0
x07
///< Function select bits mask
BCM2835_GPIO_FSEL_INPT
=
0
b0
00
,
///< Input
BCM2835_GPIO_FSEL_OUTP
=
0
b0
01
,
///< Output
BCM2835_GPIO_FSEL_ALT0
=
0
b100
,
///< Alternate function 0
BCM2835_GPIO_FSEL_ALT1
=
0
b101
,
///< Alternate function 1
BCM2835_GPIO_FSEL_ALT2
=
0
b110
,
///< Alternate function 2
BCM2835_GPIO_FSEL_ALT3
=
0
b111
,
///< Alternate function 3
BCM2835_GPIO_FSEL_ALT4
=
0
b011
,
///< Alternate function 4
BCM2835_GPIO_FSEL_ALT5
=
0
b010
,
///< Alternate function 5
BCM2835_GPIO_FSEL_MASK
=
0
b111
///< Function select bits mask
}
bcm2835FunctionSelect
;
/// \brief bcm2835PUDControl
/// Pullup/Pulldown defines for bcm2835_gpio_pud()
typedef
enum
{
BCM2835_GPIO_PUD_OFF
=
0
x
00
,
///< Off ? disable pull-up/down
BCM2835_GPIO_PUD_DOWN
=
0
x
01
,
///< Enable Pull Down control
BCM2835_GPIO_PUD_UP
=
0
x02
///< Enable Pull Up control
BCM2835_GPIO_PUD_OFF
=
0
b
00
,
///< Off ? disable pull-up/down
BCM2835_GPIO_PUD_DOWN
=
0
b
01
,
///< Enable Pull Down control
BCM2835_GPIO_PUD_UP
=
0
b10
///< Enable Pull Up control
}
bcm2835PUDControl
;
/// Pad control register offsets from BCM2835_GPIO_PADS
...
...
@@ -494,7 +534,9 @@ typedef enum
/// RPi B+ has yet differnet pinouts and these are defined in RPI_BPLUS_*.
/// At bootup, pins 8 and 10 are set to UART0_TXD, UART0_RXD (ie the alt0 function) respectively
/// When SPI0 is in use (ie after bcm2835_spi_begin()), SPI0 pins are dedicated to SPI
/// and cant be controlled independently
/// and cant be controlled independently.
/// If you are using the RPi Compute Module, just use the GPIO number: there is no need to use one of these
/// symbolic names
typedef
enum
{
RPI_GPIO_P1_03
=
0
,
///< Version 1, Pin P1-03
...
...
@@ -629,12 +671,10 @@ typedef enum
/// Specify the SPI chip select pin(s)
typedef
enum
{
// Can also use non-standard pins with this lib
BCM2835_SPI_CS0
=
0
,
///< Chip Select 0
BCM2835_SPI_CS1
=
1
,
///< Chip Select 1
BCM2835_SPI_CS2
=
2
,
///< Chip Select 2 (ie pins CS1 and CS2 are asserted)
BCM2835_SPI_CS_NONE
=
3
,
///< No CS, control it yourself
}
bcm2835SPIChipSelect
;
/// \brief bcm2835SPIClockDivider
...
...
@@ -682,6 +722,7 @@ typedef enum
#define BCM2835_SPI_SPEED_16KHZ BCM2835_SPI_CLOCK_DIVIDER_16384
#define BCM2835_SPI_SPEED_8KHZ BCM2835_SPI_CLOCK_DIVIDER_32768
// Defines for I2C
// GPIO register offsets from BCM2835_BSC*_BASE.
// Offsets into the BSC Peripheral block in bytes per 3.1 BSC Register Map
...
...
@@ -788,7 +829,6 @@ typedef enum
#define BCM2835_PWM0_SERIAL 0x0002 ///< Run in serial mode
#define BCM2835_PWM0_ENABLE 0x0001 ///< Channel Enable
/// \brief bcm2835PWMClockDivider
/// Specifies the divider used to generate the PWM clock from the system clock.
/// Figures below give the divider, clock period and clock frequency.
...
...
@@ -796,10 +836,6 @@ typedef enum
/// The frequencies shown for each divider have been confirmed by measurement
typedef
enum
{
BCM2835_PWM_CLOCK_DIVIDER_32768
=
32768
,
///< 32768 = 585Hz
BCM2835_PWM_CLOCK_DIVIDER_16384
=
16384
,
///< 16384 = 1171.8Hz
BCM2835_PWM_CLOCK_DIVIDER_8192
=
8192
,
///< 8192 = 2.34375kHz
BCM2835_PWM_CLOCK_DIVIDER_4096
=
4096
,
///< 4096 = 4.6875kHz
BCM2835_PWM_CLOCK_DIVIDER_2048
=
2048
,
///< 2048 = 9.375kHz
BCM2835_PWM_CLOCK_DIVIDER_1024
=
1024
,
///< 1024 = 18.75kHz
BCM2835_PWM_CLOCK_DIVIDER_512
=
512
,
///< 512 = 37.5kHz
...
...
@@ -859,13 +895,20 @@ extern "C" {
///
/// @{
/// Gets the base of a register
/// \param[in] regbase You can use one of the common values BCM2835_REGBASE_*
/// in \ref bcm2835RegisterBase
/// \return the register base
/// \sa Physical Addresses
extern
uint32_t
*
bcm2835_regbase
(
uint8_t
regbase
);
/// Reads 32 bit value from a peripheral address
/// The read is done twice, and is therefore always safe in terms of
/// manual section 1.3 Peripheral access precautions for correct memory ordering
/// \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc.
/// \return the value read from the 32 bit register
/// \sa Physical Addresses
extern
uint32_t
bcm2835_peri_read
(
volatile
uint32_t
*
paddr
);
extern
uint32_t
bcm2835_peri_read
(
uint32_t
*
paddr
);
/// Reads 32 bit value from a peripheral address without the read barrier
...
...
@@ -874,7 +917,7 @@ extern "C" {
/// \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc.
/// \return the value read from the 32 bit register
/// \sa Physical Addresses
extern
uint32_t
bcm2835_peri_read_nb
(
volatile
uint32_t
*
paddr
);
extern
uint32_t
bcm2835_peri_read_nb
(
uint32_t
*
paddr
);
/// Writes 32 bit value from a peripheral address
...
...
@@ -883,7 +926,7 @@ extern "C" {
/// \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc.
/// \param[in] value The 32 bit value to write
/// \sa Physical Addresses
extern
void
bcm2835_peri_write
(
volatile
uint32_t
*
paddr
,
uint32_t
value
);
extern
void
bcm2835_peri_write
(
uint32_t
*
paddr
,
uint32_t
value
);
/// Writes 32 bit value from a peripheral address without the write barrier
/// You should only use this when your code has previously called bcm2835_peri_write()
...
...
@@ -891,7 +934,7 @@ extern "C" {
/// \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc.
/// \param[in] value The 32 bit value to write
/// \sa Physical Addresses
extern
void
bcm2835_peri_write_nb
(
volatile
uint32_t
*
paddr
,
uint32_t
value
);
extern
void
bcm2835_peri_write_nb
(
uint32_t
*
paddr
,
uint32_t
value
);
/// Alters a number of bits in a 32 peripheral regsiter.
/// It reads the current valu and then alters the bits deines as 1 in mask,
...
...
@@ -904,7 +947,7 @@ extern "C" {
/// \param[in] value The 32 bit value to write, masked in by mask.
/// \param[in] mask Bitmask that defines the bits that will be altered in the register.
/// \sa Physical Addresses
extern
void
bcm2835_peri_set_bits
(
volatile
uint32_t
*
paddr
,
uint32_t
value
,
uint32_t
mask
);
extern
void
bcm2835_peri_set_bits
(
uint32_t
*
paddr
,
uint32_t
value
,
uint32_t
mask
);
/// @} // end of lowlevel
/// \defgroup gpio GPIO register access
...
...
@@ -1107,89 +1150,79 @@ extern "C" {
/// \param[in] pud The desired Pull-up/down mode. One of BCM2835_GPIO_PUD_* from bcm2835PUDControl
extern
void
bcm2835_gpio_set_pud
(
uint8_t
pin
,
uint8_t
pud
);
/// @}
/// @}
/// \defgroup spi SPI access
/// These functions let you use SPI0 (Serial Peripheral Interface) to
/// These functions let you use SPI0 (Serial Peripheral Interface) to
/// interface with an external SPI device.
/// @{
/// Start SPI operations.
/// Forces RPi SPI0 pins P1-19 (MOSI), P1-21 (MISO), P1-23 (CLK), P1-24 (CE0) and P1-26 (CE1)
/// to alternate function ALT0, which enables those pins for SPI interface.
/// \param[in] cs Specifies the CS pins(s) that are used to activate the desired slave.
/// One of BCM2835_SPI_CS*, see \ref bcm2835SPIChipSelect
/// or one of One of BCM2835_SPI_CS*, see \ref bcm2835SPIChipSelect
/// by default PI hardware driven using CE0
/// You should call bcm2835_spi_end() when all SPI funcitons are complete to return the pins to
/// 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
();
extern
void
bcm2835_spi_begin
(
void
);
/// End SPI operations.
/// SPI0 pins P1-19 (MOSI), P1-21 (MISO), P1-23 (CLK), P1-24 (CE0) and P1-26 (CE1)
/// are returned to their default INPUT behaviour.
extern
void
bcm2835_spi_end
(
void
);
/// Sets the SPI custom Chip Select pin to correct level
/// Defaults to
/// \param[in] level The desired level, LOW or HIGH,
extern
void
bcm2835_spi_setChipSelect
(
uint8_t
level
);
/// Sets the SPI bit order
/// NOTE: has no effect. Not supported by SPI0.
/// Defaults to
/// \param[in] order The desired bit order, one of BCM2835_SPI_BIT_ORDER_*,
/// Defaults to
/// \param[in] order The desired bit order, one of BCM2835_SPI_BIT_ORDER_*,
/// see \ref bcm2835SPIBitOrder
extern
void
bcm2835_spi_setBitOrder
(
uint8_t
order
);
/// Sets the SPI clock divider and therefore the
/// SPI clock speed.
/// \param[in] divider The desired SPI clock divider, one of BCM2835_SPI_CLOCK_DIVIDER_*,
/// Sets the SPI clock divider and therefore the
/// SPI clock speed.
/// \param[in] divider The desired SPI clock divider, one of BCM2835_SPI_CLOCK_DIVIDER_*,
/// see \ref bcm2835SPIClockDivider
extern
void
bcm2835_spi_setClockDivider
(
uint16_t
divider
);
/// Sets the SPI data mode
/// Sets the clock polariy and phase
/// \param[in] mode The desired data mode, one of BCM2835_SPI_MODE*,
/// \param[in] mode The desired data mode, one of BCM2835_SPI_MODE*,
/// see \ref bcm2835SPIMode
extern
void
bcm2835_spi_setDataMode
(
uint8_t
mode
);
/// Sets the chip select pin(s)
/// When an bcm2835_spi_transfer() is made, the selected pin(s) will be asserted during the
/// transfer.
/// \param[in] cs Specifies the CS pins(s) that are used to activate the desired slave.
/// \param[in] cs Specifies the CS pins(s) that are used to activate the desired slave.
/// One of BCM2835_SPI_CS*, see \ref bcm2835SPIChipSelect
/// or one of One of BCM2835_SPI_CS*, see \ref bcm2835SPIChipSelect
extern
void
bcm2835_spi_chipSelect
(
uint8_t
cs
);
/// Sets the chip select pin polarity for a given pin
/// When an bcm2835_spi_transfer() occurs, the currently selected chip select pin(s)
/// will be asserted to the
/// value given by active. When transfers are not happening, the chip select pin(s)
/// When an bcm2835_spi_transfer() occurs, the currently selected chip select pin(s)
/// will be asserted to the
/// value given by active. When transfers are not happening, the chip select pin(s)
/// return to the complement (inactive) value.
/// \param[in] cs The chip select pin to affect
/// \param[in] active Whether the chip select pin is to be active HIGH
extern
void
bcm2835_spi_setChipSelectPolarity
(
uint8_t
cs
,
uint8_t
active
);
/// Transfers one byte to and from the currently selected SPI slave.
/// Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect)
/// Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect)
/// during the transfer.
/// Clocks the 8 bit value out on MOSI, and simultaneously clocks in data from MISO.
/// Clocks the 8 bit value out on MOSI, and simultaneously clocks in data from MISO.
/// Returns the read data byte from the slave.
/// Uses polled transfer as per section 10.6.1 of the BCM 2835 ARM Peripherls manual
/// \param[in] value The 8 bit data byte to write to MOSI
/// \return The 8 bit byte simultaneously read from MISO
/// \sa bcm2835_spi_transfern()
extern
uint8_t
bcm2835_spi_transfer
(
uint8_t
value
);
/// Transfers any number of bytes to and from the currently selected SPI slave.
/// Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect)
/// Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect)
/// during the transfer.
/// Clocks the len 8 bit bytes out on MOSI, and simultaneously clocks in data from MISO.
/// Clocks the len 8 bit bytes out on MOSI, and simultaneously clocks in data from MISO.
/// The data read read from the slave is placed into rbuf. rbuf must be at least len bytes long
/// Uses polled transfer as per section 10.6.1 of the BCM 2835 ARM Peripherls manual
/// \param[in] tbuf Buffer of bytes to send.
/// \param[in] tbuf Buffer of bytes to send.
/// \param[out] rbuf Received bytes will by put in this buffer
/// \param[in] len Number of bytes in the tbuf buffer, and the number of bytes to send/received
/// \sa bcm2835_spi_transfer()
...
...
@@ -1301,7 +1334,7 @@ extern "C" {
/// \param[in] micros Delay in microseconds
extern
void
bcm2835_st_delay
(
uint64_t
offset_micros
,
uint64_t
micros
);
/// @}
/// @}
/// \defgroup pwm Pulse Width Modulation
/// Allows control of 2 independent PWM channels. A limited subset of GPIO pins
...
...
@@ -1310,12 +1343,12 @@ extern "C" {
/// documentation on the Main Page.
/// @{
/// Sets the PWM clock divisor,
/// Sets the PWM clock divisor,
/// to control the basic PWM pulse widths.
/// \param[in] divisor Divides the basic 19.2MHz PWM clock. You can use one of the common
/// values BCM2835_PWM_CLOCK_DIVIDER_* in \ref bcm2835PWMClockDivider
extern
void
bcm2835_pwm_set_clock
(
uint32_t
divisor
);
/// Sets the mode of the given PWM channel,
/// allowing you to control the PWM mode and enable/disable that channel
/// \param[in] channel The PWM channel. 0 or 1.
...
...
@@ -1328,15 +1361,15 @@ extern "C" {
/// \param[in] channel The PWM channel. 0 or 1.
/// \param[in] range The maximum value permitted for DATA.
extern
void
bcm2835_pwm_set_range
(
uint8_t
channel
,
uint32_t
range
);
/// Sets the PWM pulse ratio to emit to DATA/RANGE,
/// Sets the PWM pulse ratio to emit to DATA/RANGE,
/// where RANGE is set by bcm2835_pwm_set_range().
/// \param[in] channel The PWM channel. 0 or 1.
/// \param[in] data Controls the PWM output ratio as a fraction of the range.
/// \param[in] data Controls the PWM output ratio as a fraction of the range.
/// Can vary from 0 to RANGE.
extern
void
bcm2835_pwm_set_data
(
uint8_t
channel
,
uint32_t
data
);
/// @}
/// @}
#ifdef __cplusplus
}
#endif
...
...
@@ -1362,9 +1395,9 @@ extern "C" {
/// Shows how to use PWM to control GPIO pins
/// @example i2c.c
/// Command line utility for executing i2c commands with the
/// Command line utility for executing i2c commands with the
/// Broadcom bcm2835. Contributed by Shahrooz Shahparnia.
/// example gpio.c
/// Command line utility for executing gpio commands with the
/// Command line utility for executing gpio commands with the
/// Broadcom bcm2835. Contributed by Shahrooz Shahparnia.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment