From fe0a70185782e5598f2f1f4856caaf186242c116 Mon Sep 17 00:00:00 2001 From: Romeo-Golf Date: Mon, 2 Jan 2017 23:35:48 +0000 Subject: [PATCH 1/2] Merge of upstream @ http://www.airspayce.com/mikem/bcm2835/bcm2835-1.50.tar.gz --- Makefile.in | 277 ++-- aclocal.m4 | 371 +++-- config.h.in | 2 +- configure | 89 +- configure.in => configure.ac | 4 +- doc/Makefile.in | 105 +- examples/blink/blink.c | 3 +- examples/i2c/i2c.c | 16 +- examples/spi/spi.c | 23 +- examples/spin/spin.c | 12 +- src/Makefile.am | 1 + src/Makefile.in | 627 ++++++--- src/bcm2835.c | 909 ++++++++----- src/bcm2835.h | 2497 +++++++++++++++++++--------------- src/test.c | 2 +- test-driver | 127 ++ 16 files changed, 3144 insertions(+), 1921 deletions(-) rename configure.in => configure.ac (81%) create mode 100755 test-driver diff --git a/Makefile.in b/Makefile.in index ce857bd..cb1a44b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.12.1 from Makefile.am. +# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2012 Free Software Foundation, Inc. +# Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -14,23 +14,51 @@ @SET_MAKE@ VPATH = @srcdir@ -am__make_dryrun = \ - { \ - am__dry=no; \ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ - echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ - | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ - *) \ - for am__flg in $$MAKEFLAGS; do \ - case $$am__flg in \ - *=*|--*) ;; \ - *n*) am__dry=yes; break;; \ - esac; \ - done;; \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ esac; \ - test $$am__dry = yes; \ - } + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -48,12 +76,13 @@ NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : subdir = . -DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \ - $(srcdir)/Makefile.in $(srcdir)/config.h.in \ - $(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \ - config.guess config.sub depcomp install-sh ltmain.sh missing +DIST_COMMON = INSTALL NEWS README AUTHORS ChangeLog \ + $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/configure $(am__configure_deps) \ + $(srcdir)/config.h.in COPYING config.guess config.sub depcomp \ + install-sh missing ltmain.sh ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ @@ -62,15 +91,28 @@ mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = SOURCES = DIST_SOURCES = -RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ - html-recursive info-recursive install-data-recursive \ - install-dvi-recursive install-exec-recursive \ - install-html-recursive install-info-recursive \ - install-pdf-recursive install-ps-recursive install-recursive \ - installcheck-recursive installdirs-recursive pdf-recursive \ - ps-recursive uninstall-recursive +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ @@ -78,9 +120,30 @@ am__can_run_installinfo = \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive -AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ - $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ cscope distdir dist dist-all distcheck +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ + $(LISP)config.h.in +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags CSCOPE = cscope @@ -129,6 +192,7 @@ am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ @@ -284,17 +348,20 @@ distclean-hdr: # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. -$(RECURSIVE_TARGETS): - @fail= failcom='exit 1'; \ - for f in x $$MAKEFLAGS; do \ - case $$f in \ - *=* | --[!k]*);; \ - *k*) failcom='fail=yes';; \ - esac; \ - done; \ +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ - list='$(SUBDIRS)'; for subdir in $$list; do \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ @@ -309,61 +376,12 @@ $(RECURSIVE_TARGETS): $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" -$(RECURSIVE_CLEAN_TARGETS): - @fail= failcom='exit 1'; \ - for f in x $$MAKEFLAGS; do \ - case $$f in \ - *=* | --[!k]*);; \ - *k*) failcom='fail=yes';; \ - esac; \ - done; \ - dot_seen=no; \ - case "$@" in \ - distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ - *) list='$(SUBDIRS)' ;; \ - esac; \ - rev=''; for subdir in $$list; do \ - if test "$$subdir" = "."; then :; else \ - rev="$$subdir $$rev"; \ - fi; \ - done; \ - rev="$$rev ."; \ - target=`echo $@ | sed s/-recursive//`; \ - for subdir in $$rev; do \ - echo "Making $$target in $$subdir"; \ - if test "$$subdir" = "."; then \ - local_target="$$target-am"; \ - else \ - local_target="$$target"; \ - fi; \ - ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ - || eval $$failcom; \ - done && test -z "$$fail" -tags-recursive: - list='$(SUBDIRS)'; for subdir in $$list; do \ - test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ - done -ctags-recursive: - list='$(SUBDIRS)'; for subdir in $$list; do \ - test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ - done -cscopelist-recursive: - list='$(SUBDIRS)'; for subdir in $$list; do \ - test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) cscopelist); \ - done +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags -ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - mkid -fID $$unique -tags: TAGS - -TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ @@ -379,12 +397,7 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ - list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ + $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ @@ -396,15 +409,11 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $$unique; \ fi; \ fi -ctags: CTAGS -CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique @@ -413,18 +422,16 @@ GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" - cscope: cscope.files test ! -s cscope.files \ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) - clean-cscope: -rm -f cscope.files +cscope.files: clean-cscope cscopelist +cscopelist: cscopelist-recursive -cscope.files: clean-cscope cscopelist-recursive cscopelist - -cscopelist: cscopelist-recursive $(HEADERS) $(SOURCES) $(LISP) - list='$(SOURCES) $(HEADERS) $(LISP)'; \ +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ @@ -558,9 +565,9 @@ distcheck: dist *.zip*) \ unzip $(distdir).zip ;;\ esac - chmod -R a-w $(distdir); chmod a+w $(distdir) - mkdir $(distdir)/_build - mkdir $(distdir)/_inst + chmod -R a-w $(distdir) + chmod u+w $(distdir) + mkdir $(distdir)/_build $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ @@ -727,25 +734,23 @@ ps-am: uninstall-am: -.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all \ - cscopelist-recursive ctags-recursive install-am install-strip \ - tags-recursive - -.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ - all all-am am--refresh check check-am clean clean-cscope \ - clean-generic cscope cscopelist cscopelist-recursive ctags \ - ctags-recursive dist dist-all dist-bzip2 dist-gzip dist-lzip \ - dist-shar dist-tarZ dist-xz dist-zip distcheck distclean \ - distclean-generic distclean-hdr distclean-tags distcleancheck \ - distdir distuninstallcheck dvi dvi-am html html-am info \ - info-am install install-am install-data install-data-am \ - install-dvi install-dvi-am install-exec install-exec-am \ - install-html install-html-am install-info install-info-am \ - install-man install-pdf install-pdf-am install-ps \ - install-ps-am install-strip installcheck installcheck-am \ - installdirs installdirs-am maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ - pdf-am ps ps-am tags tags-recursive uninstall uninstall-am +.MAKE: $(am__recursive_targets) all install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ + am--refresh check check-am clean clean-cscope clean-generic \ + cscope cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \ + dist-gzip dist-lzip dist-shar dist-tarZ dist-xz dist-zip \ + distcheck distclean distclean-generic distclean-hdr \ + distclean-tags distcleancheck distdir distuninstallcheck dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs installdirs-am \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am upload: diff --git a/aclocal.m4 b/aclocal.m4 index 15a6f5f..f63de05 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -1,6 +1,6 @@ -# generated automatically by aclocal 1.12.1 -*- Autoconf -*- +# generated automatically by aclocal 1.13.4 -*- Autoconf -*- -# Copyright (C) 1996-2012 Free Software Foundation, Inc. +# Copyright (C) 1996-2013 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -11,6 +11,7 @@ # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. +m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, @@ -19,24 +20,22 @@ You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) -# Copyright (C) 2002-2012 Free Software Foundation, Inc. +# Copyright (C) 2002-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 8 - # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], -[am__api_version='1.12' +[am__api_version='1.13' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. -m4_if([$1], [1.12.1], [], +m4_if([$1], [1.13.4], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) @@ -52,21 +51,19 @@ m4_define([_AM_AUTOCONF_VERSION], []) # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], -[AM_AUTOMAKE_VERSION([1.12.1])dnl +[AM_AUTOMAKE_VERSION([1.13.4])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- -# Copyright (C) 2001-2012 Free Software Foundation, Inc. +# Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 2 - # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to # '$srcdir', '$srcdir/..', or '$srcdir/../..'. @@ -114,14 +111,12 @@ am_aux_dir=`cd $ac_aux_dir && pwd` # AM_COND_IF -*- Autoconf -*- -# Copyright (C) 2008-2012 Free Software Foundation, Inc. +# Copyright (C) 2008-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 3 - # _AM_COND_IF # _AM_COND_ELSE # _AM_COND_ENDIF @@ -131,7 +126,6 @@ m4_define([_AM_COND_IF]) m4_define([_AM_COND_ELSE]) m4_define([_AM_COND_ENDIF]) - # AM_COND_IF(COND, [IF-TRUE], [IF-FALSE]) # --------------------------------------- # If the shell condition COND is true, execute IF-TRUE, otherwise execute @@ -154,14 +148,12 @@ fi[]dnl # AM_CONDITIONAL -*- Autoconf -*- -# Copyright (C) 1997-2012 Free Software Foundation, Inc. +# Copyright (C) 1997-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 10 - # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. @@ -187,13 +179,12 @@ AC_CONFIG_COMMANDS_PRE( Usually this means the macro was only invoked conditionally.]]) fi])]) -# Copyright (C) 1999-2012 Free Software Foundation, Inc. +# Copyright (C) 1999-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 17 # There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, @@ -379,19 +370,18 @@ _AM_SUBST_NOTMAKE([am__nodep])dnl # Generate code to set up dependency tracking. -*- Autoconf -*- -# Copyright (C) 1999-2012 Free Software Foundation, Inc. +# Copyright (C) 1999-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 6 # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ - # Autoconf 2.62 quotes --file arguments for eval, but not when files + # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in @@ -420,7 +410,7 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` - test -z "am__include" && continue + test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the @@ -454,27 +444,14 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) -# Copyright (C) 1996-2012 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 8 - -# AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS. -AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)]) - # Do all the work for Automake. -*- Autoconf -*- -# Copyright (C) 1996-2012 Free Software Foundation, Inc. +# Copyright (C) 1996-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 19 - # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. @@ -490,7 +467,7 @@ AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)]) # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], -[AC_PREREQ([2.62])dnl +[AC_PREREQ([2.65])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl @@ -520,8 +497,7 @@ AC_SUBST([CYGPATH_W]) dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [AC_DIAGNOSE([obsolete], -[$0: two- and three-arguments forms are deprecated. For more info, see: -http://www.gnu.org/software/automake/manual/automake.html#Modernize-AM_INIT_AUTOMAKE-invocation]) + [$0: two- and three-arguments forms are deprecated.]) m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], @@ -549,7 +525,11 @@ AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl -AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target. The system "awk" is bad on # some platforms. AC_REQUIRE([AC_PROG_AWK])dnl @@ -571,18 +551,15 @@ AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl -dnl Support for Objective C++ was only introduced in Autoconf 2.65, -dnl but we still cater to Autoconf 2.62. -m4_ifdef([AC_PROG_OBJCXX], -[AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], +AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], - m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])])dnl + m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl ]) -_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl -dnl The 'parallel-tests' driver may need to know about EXEEXT, so add the -dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro -dnl is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_REQUIRE([AM_SILENT_RULES])dnl +dnl The testsuite driver may need to know about EXEEXT, so add the +dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This +dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl @@ -616,14 +593,12 @@ for _am_header in $config_headers :; do done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) -# Copyright (C) 2001-2012 Free Software Foundation, Inc. +# Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 8 - # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. @@ -639,14 +614,12 @@ if test x"${install_sh}" != xset; then fi AC_SUBST([install_sh])]) -# Copyright (C) 2003-2012 Free Software Foundation, Inc. +# Copyright (C) 2003-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 2 - # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], @@ -662,14 +635,12 @@ AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- -# Copyright (C) 2001-2012 Free Software Foundation, Inc. +# Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 5 - # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. @@ -714,14 +685,12 @@ rm -f confinc confmf # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- -# Copyright (C) 1997-2012 Free Software Foundation, Inc. +# Copyright (C) 1997-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 7 - # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], @@ -729,11 +698,10 @@ AC_DEFUN([AM_MISSING_PROG], $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) - # AM_MISSING_HAS_RUN # ------------------ -# Define MISSING if not defined so far and test if it supports --run. -# If it does, set am_missing_run to use it, otherwise, to nothing. +# Define MISSING if not defined so far and test if it is modern enough. +# If it is, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl @@ -746,24 +714,51 @@ if test x"${MISSING+set}" != xset; then esac fi # Use eval to expand $SHELL -if eval "$MISSING --run true"; then - am_missing_run="$MISSING --run " +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) +# -*- Autoconf -*- +# Obsolete and "removed" macros, that must however still report explicit +# error messages when used, to smooth transition. +# +# Copyright (C) 1996-2013 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +AC_DEFUN([AM_CONFIG_HEADER], +[AC_DIAGNOSE([obsolete], +['$0': this macro is obsolete. +You should use the 'AC][_CONFIG_HEADERS' macro instead.])dnl +AC_CONFIG_HEADERS($@)]) + +AC_DEFUN([AM_PROG_CC_STDC], +[AC_PROG_CC +am_cv_prog_cc_stdc=$ac_cv_prog_cc_stdc +AC_DIAGNOSE([obsolete], +['$0': this macro is obsolete. +You should simply use the 'AC][_PROG_CC' macro instead. +Also, your code should no longer depend upon 'am_cv_prog_cc_stdc', +but upon 'ac_cv_prog_cc_stdc'.])]) + +AC_DEFUN([AM_C_PROTOTYPES], + [AC_FATAL([automatic de-ANSI-fication support has been removed])]) +AU_DEFUN([fp_C_PROTOTYPES], [AM_C_PROTOTYPES]) + # Helper functions for option handling. -*- Autoconf -*- -# Copyright (C) 2001-2012 Free Software Foundation, Inc. +# Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 6 - # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], @@ -789,14 +784,12 @@ AC_DEFUN([_AM_IF_OPTION], # Check to make sure that the build environment is sane. -*- Autoconf -*- -# Copyright (C) 1996-2012 Free Software Foundation, Inc. +# Copyright (C) 1996-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 9 - # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], @@ -872,13 +865,71 @@ AC_CONFIG_COMMANDS_PRE( rm -f conftest.file ]) -# Copyright (C) 2001-2012 Free Software Foundation, Inc. +# Copyright (C) 2009-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 2 +# AM_SILENT_RULES([DEFAULT]) +# -------------------------- +# Enable less verbose build rules; with the default set to DEFAULT +# ("yes" being less verbose, "no" or empty being verbose). +AC_DEFUN([AM_SILENT_RULES], +[AC_ARG_ENABLE([silent-rules], [dnl +AS_HELP_STRING( + [--enable-silent-rules], + [less verbose build output (undo: "make V=1")]) +AS_HELP_STRING( + [--disable-silent-rules], + [verbose build output (undo: "make V=0")])dnl +]) +case $enable_silent_rules in @%:@ ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; +esac +dnl +dnl A few 'make' implementations (e.g., NonStop OS and NextStep) +dnl do not support nested variable expansions. +dnl See automake bug#9928 and bug#10237. +am_make=${MAKE-make} +AC_CACHE_CHECK([whether $am_make supports nested variables], + [am_cv_make_support_nested_variables], + [if AS_ECHO([['TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi]) +if test $am_cv_make_support_nested_variables = yes; then + dnl Using '$V' instead of '$(V)' breaks IRIX make. + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AC_SUBST([AM_V])dnl +AM_SUBST_NOTMAKE([AM_V])dnl +AC_SUBST([AM_DEFAULT_V])dnl +AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl +AC_SUBST([AM_DEFAULT_VERBOSITY])dnl +AM_BACKSLASH='\' +AC_SUBST([AM_BACKSLASH])dnl +_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl +]) + +# Copyright (C) 2001-2013 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- @@ -902,14 +953,12 @@ fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) -# Copyright (C) 2006-2012 Free Software Foundation, Inc. +# Copyright (C) 2006-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 3 - # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. @@ -923,14 +972,12 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- -# Copyright (C) 2004-2012 Free Software Foundation, Inc. +# Copyright (C) 2004-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 3 - # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. @@ -944,76 +991,114 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar +# AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) -m4_if([$1], [v7], - [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], - [m4_case([$1], [ustar],, [pax],, - [m4_fatal([Unknown tar format])]) -AC_MSG_CHECKING([how to create a $1 tar archive]) -# Loop over all known methods to create a tar archive until one works. + +# We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' -_am_tools=${am_cv_prog_tar_$1-$_am_tools} -# Do not fold the above two line into one, because Tru64 sh and -# Solaris sh will not grok spaces in the rhs of '-'. -for _am_tool in $_am_tools -do - case $_am_tool in - gnutar) - for _am_tar in tar gnutar gtar; - do - AM_RUN_LOG([$_am_tar --version]) && break - done - am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' - am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' - am__untar="$_am_tar -xf -" - ;; - plaintar) - # Must skip GNU tar: if it does not support --format= it doesn't create - # ustar tarball either. - (tar --version) >/dev/null 2>&1 && continue - am__tar='tar chf - "$$tardir"' - am__tar_='tar chf - "$tardir"' - am__untar='tar xf -' - ;; - pax) - am__tar='pax -L -x $1 -w "$$tardir"' - am__tar_='pax -L -x $1 -w "$tardir"' - am__untar='pax -r' - ;; - cpio) - am__tar='find "$$tardir" -print | cpio -o -H $1 -L' - am__tar_='find "$tardir" -print | cpio -o -H $1 -L' - am__untar='cpio -i -H $1 -d' - ;; - none) - am__tar=false - am__tar_=false - am__untar=false - ;; - esac - # If the value was cached, stop now. We just wanted to have am__tar - # and am__untar set. - test -n "${am_cv_prog_tar_$1}" && break +m4_if([$1], [v7], + [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], + + [m4_case([$1], + [ustar], + [# The POSIX 1988 'ustar' format is defined with fixed-size fields. + # There is notably a 21 bits limit for the UID and the GID. In fact, + # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 + # and bug#13588). + am_max_uid=2097151 # 2^21 - 1 + am_max_gid=$am_max_uid + # The $UID and $GID variables are not portable, so we need to resort + # to the POSIX-mandated id(1) utility. Errors in the 'id' calls + # below are definitely unexpected, so allow the users to see them + # (that is, avoid stderr redirection). + am_uid=`id -u || echo unknown` + am_gid=`id -g || echo unknown` + AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) + if test $am_uid -le $am_max_uid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi + AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) + if test $am_gid -le $am_max_gid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi], + + [pax], + [], + + [m4_fatal([Unknown tar format])]) + + AC_MSG_CHECKING([how to create a $1 tar archive]) + + # Go ahead even if we have the value already cached. We do so because we + # need to set the values for the 'am__tar' and 'am__untar' variables. + _am_tools=${am_cv_prog_tar_$1-$_am_tools} + + for _am_tool in $_am_tools; do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac - # tar/untar a dummy directory, and stop if the command works - rm -rf conftest.dir - mkdir conftest.dir - echo GrepMe > conftest.dir/file - AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works. + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi + done rm -rf conftest.dir - if test -s conftest.tar; then - AM_RUN_LOG([$am__untar /dev/null 2>&1 && break - fi -done -rm -rf conftest.dir -AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) -AC_MSG_RESULT([$am_cv_prog_tar_$1])]) + AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) + AC_MSG_RESULT([$am_cv_prog_tar_$1])]) + AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR diff --git a/config.h.in b/config.h.in index 695dc73..3ae97f2 100644 --- a/config.h.in +++ b/config.h.in @@ -1,4 +1,4 @@ -/* config.h.in. Generated from configure.in by autoheader. */ +/* config.h.in. Generated from configure.ac by autoheader. */ /* Define to 1 if you have the `rt' library (-lrt). */ #undef HAVE_LIBRT diff --git a/configure b/configure index c8d6642..10471de 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for bcm2835 1.36. +# Generated by GNU Autoconf 2.69 for bcm2835 1.50. # # Report bugs to . # @@ -579,8 +579,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='bcm2835' PACKAGE_TARNAME='bcm2835' -PACKAGE_VERSION='1.36' -PACKAGE_STRING='bcm2835 1.36' +PACKAGE_VERSION='1.50' +PACKAGE_STRING='bcm2835 1.50' PACKAGE_BUGREPORT='mikem@airspayce.com' PACKAGE_URL='' @@ -609,6 +609,10 @@ CPPFLAGS LDFLAGS CFLAGS CC +AM_BACKSLASH +AM_DEFAULT_VERBOSITY +AM_DEFAULT_V +AM_V am__untar am__tar AMTAR @@ -673,6 +677,7 @@ SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking +enable_silent_rules enable_dependency_tracking ' ac_precious_vars='build_alias @@ -1223,7 +1228,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures bcm2835 1.36 to adapt to many kinds of systems. +\`configure' configures bcm2835 1.50 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1289,7 +1294,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of bcm2835 1.36:";; + short | recursive ) echo "Configuration of bcm2835 1.50:";; esac cat <<\_ACEOF @@ -1297,6 +1302,8 @@ Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-silent-rules less verbose build output (undo: "make V=1") + --disable-silent-rules verbose build output (undo: "make V=0") --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking @@ -1377,7 +1384,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -bcm2835 configure 1.36 +bcm2835 configure 1.50 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1478,7 +1485,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by bcm2835 $as_me 1.36, which was +It was created by bcm2835 $as_me 1.50, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -1829,7 +1836,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_headers="$ac_config_headers config.h" -am__api_version='1.12' +am__api_version='1.13' ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do @@ -2042,8 +2049,8 @@ if test x"${MISSING+set}" != xset; then esac fi # Use eval to expand $SHELL -if eval "$MISSING --run true"; then - am_missing_run="$MISSING --run " +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " else am_missing_run= { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 @@ -2283,6 +2290,45 @@ else fi rmdir .tst 2>/dev/null +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=1;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." @@ -2305,7 +2351,7 @@ fi # Define the identity of the package. PACKAGE='bcm2835' - VERSION='1.36' + VERSION='1.50' cat >>confdefs.h <<_ACEOF @@ -2333,19 +2379,29 @@ AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} -mkdir_p="$MKDIR_P" +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +mkdir_p='$(MKDIR_P)' + # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar pax cpio none' + am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' + DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" @@ -4286,7 +4342,6 @@ DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= -U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' @@ -4730,7 +4785,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by bcm2835 $as_me 1.36, which was +This file was extended by bcm2835 $as_me 1.50, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -4796,7 +4851,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -bcm2835 config.status 1.36 +bcm2835 config.status 1.50 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" @@ -5527,7 +5582,7 @@ $as_echo "$as_me: executing $ac_file commands" >&6;} case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { - # Autoconf 2.62 quotes --file arguments for eval, but not when files + # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in @@ -5578,7 +5633,7 @@ $as_echo X"$mf" | DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` - test -z "am__include" && continue + test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the diff --git a/configure.in b/configure.ac similarity index 81% rename from configure.in rename to configure.ac index 8e78ebc..206a305 100644 --- a/configure.in +++ b/configure.ac @@ -4,7 +4,9 @@ dnl dnl $Id: configure.in,v 1.1 2012/12/01 22:56:52 mikem Exp mikem $ dnl (C) 2012 Mike McCauley (mikem@airspayce.com) -AC_INIT([bcm2835], [1.36], [mikem@airspayce.com]) +dnl Dont forget to update BCM2835_VERSION and .tar.gz in bcm2835.h +dnl and the zip file. +AC_INIT([bcm2835], [1.50], [mikem@airspayce.com]) AM_CONFIG_HEADER(config.h) AM_INIT_AUTOMAKE() diff --git a/doc/Makefile.in b/doc/Makefile.in index 247c97e..5d96bb6 100644 --- a/doc/Makefile.in +++ b/doc/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.12.1 from Makefile.am. +# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2012 Free Software Foundation, Inc. +# Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -14,23 +14,51 @@ @SET_MAKE@ VPATH = @srcdir@ -am__make_dryrun = \ - { \ - am__dry=no; \ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ - echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ - | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ - *) \ - for am__flg in $$MAKEFLAGS; do \ - case $$am__flg in \ - *=*|--*) ;; \ - *n*) am__dry=yes; break;; \ - esac; \ - done;; \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ esac; \ - test $$am__dry = yes; \ - } + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -48,16 +76,28 @@ NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : subdir = doc -DIST_COMMON = $(srcdir)/Doxyfile.in $(srcdir)/Makefile.am \ - $(srcdir)/Makefile.in +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(srcdir)/Doxyfile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = Doxyfile CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ @@ -65,9 +105,11 @@ am__can_run_installinfo = \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ @@ -187,11 +229,9 @@ $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(am__aclocal_m4_deps): @HAVE_DOXYGEN_TRUE@Doxyfile: $(top_builddir)/config.status $(srcdir)/Doxyfile.in @HAVE_DOXYGEN_TRUE@ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -tags: TAGS -TAGS: +tags TAGS: -ctags: CTAGS -CTAGS: +ctags CTAGS: cscope cscopelist: @@ -332,15 +372,16 @@ uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am all-local check check-am clean clean-generic \ - clean-local distclean distclean-generic distdir dvi dvi-am \ - html html-am info info-am install install-am install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am install-info \ - install-info-am install-man install-pdf install-pdf-am \ - install-ps install-ps-am install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ - pdf-am ps ps-am uninstall uninstall-am + clean-local cscopelist-am ctags-am distclean distclean-generic \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic pdf pdf-am ps ps-am tags-am uninstall \ + uninstall-am @HAVE_DOXYGEN_TRUE@doxyfile.stamp: ../src/bcm2835.h diff --git a/examples/blink/blink.c b/examples/blink/blink.c index ae56e0b..4fc551a 100644 --- a/examples/blink/blink.c +++ b/examples/blink/blink.c @@ -17,6 +17,7 @@ // $Id: RF22.h,v 1.21 2012/05/30 01:51:25 mikem Exp $ #include +#include // Blinks on RPi Plug P1 pin 11 (which is GPIO pin 17) #define PIN RPI_GPIO_P1_11 @@ -28,7 +29,7 @@ int main(int argc, char **argv) // bcm2835_set_debug(1); if (!bcm2835_init()) - return 1; + return 1; // Set the pin to be an output bcm2835_gpio_fsel(PIN, BCM2835_GPIO_FSEL_OUTP); diff --git a/examples/i2c/i2c.c b/examples/i2c/i2c.c index 8c5ddf3..781106a 100644 --- a/examples/i2c/i2c.c +++ b/examples/i2c/i2c.c @@ -226,10 +226,22 @@ int main(int argc, char **argv) { // parse the command line if (comparse(argc, argv) == EXIT_FAILURE) return showusage (EXIT_FAILURE); - if (!bcm2835_init()) return 1; + if (!bcm2835_init()) + { + printf("bcm2835_init failed. Are you running as root??\n"); + return 1; + } // I2C begin if specified - if (init == I2C_BEGIN) bcm2835_i2c_begin(); + if (init == I2C_BEGIN) + { + if (!bcm2835_i2c_begin()) + { + printf("bcm2835_i2c_begin failed. Are you running as root??\n"); + return 1; + } + } + // If len is 0, no need to continue, but do I2C end if specified if (len == 0) { diff --git a/examples/spi/spi.c b/examples/spi/spi.c index 63df70c..7f80c99 100644 --- a/examples/spi/spi.c +++ b/examples/spi/spi.c @@ -25,21 +25,30 @@ int main(int argc, char **argv) // Use for testing // bcm2835_set_debug(1); - if (!bcm2835_init()) - return 1; + if (!bcm2835_init()) + { + printf("bcm2835_init failed. Are you running as root??\n"); + return 1; + } - bcm2835_spi_begin(); + if (!bcm2835_spi_begin()) + { + printf("bcm2835_spi_begin failedg. Are you running as root??\n"); + return 1; + } bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_MSBFIRST); // The default bcm2835_spi_setDataMode(BCM2835_SPI_MODE0); // The default bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_65536); // The default bcm2835_spi_chipSelect(BCM2835_SPI_CS0); // The default bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, LOW); // the default - + // Send a byte to the slave and simultaneously read a byte back from the slave // If you tie MISO to MOSI, you should read back what was sent - uint8_t data = bcm2835_spi_transfer(0x23); - printf("Read from SPI: %02X\n", data); - + uint8_t send_data = 0x23; + uint8_t read_data = bcm2835_spi_transfer(send_data); + printf("Sent to SPI: 0x%02X. Read back from SPI: 0x%02X.\n", send_data, read_data); + if (send_data != read_data) + printf("Do you have the loopback from MOSI to MISO connected?\n"); bcm2835_spi_end(); bcm2835_close(); return 0; diff --git a/examples/spin/spin.c b/examples/spin/spin.c index 5d12e4c..71a346f 100644 --- a/examples/spin/spin.c +++ b/examples/spin/spin.c @@ -26,8 +26,16 @@ int main(int argc, char **argv) // bcm2835_set_debug(1); if (!bcm2835_init()) - return 1; - + { + printf("bcm2835_init failed. Are you running as root??\n"); + return 1; + } + + if (!bcm2835_spi_begin()) + { + printf("bcm2835_spi_begin failed. Are you running as root??\n"); + return 1; + } bcm2835_spi_begin(); bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_MSBFIRST); // The default bcm2835_spi_setDataMode(BCM2835_SPI_MODE0); // The default diff --git a/src/Makefile.am b/src/Makefile.am index a7075db..3b9b184 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -6,3 +6,4 @@ test_SOURCES = test.c test_LDADD = ./libbcm2835.a TESTS = $(check_PROGRAMS) CLEANFILES = *~ + diff --git a/src/Makefile.in b/src/Makefile.in index 6d7da13..6ab558e 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.12.1 from Makefile.am. +# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2012 Free Software Foundation, Inc. +# Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -16,23 +16,51 @@ VPATH = @srcdir@ -am__make_dryrun = \ - { \ - am__dry=no; \ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ - echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ - | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ - *) \ - for am__flg in $$MAKEFLAGS; do \ - case $$am__flg in \ - *=*|--*) ;; \ - *n*) am__dry=yes; break;; \ - esac; \ - done;; \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ - test $$am__dry = yes; \ - } + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -51,10 +79,11 @@ PRE_UNINSTALL = : POST_UNINSTALL = : check_PROGRAMS = test$(EXEEXT) subdir = src -DIST_COMMON = $(include_HEADERS) $(srcdir)/Makefile.am \ - $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/depcomp $(include_HEADERS) \ + $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -92,6 +121,10 @@ am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)" LIBRARIES = $(lib_LIBRARIES) AR = ar ARFLAGS = cru +AM_V_AR = $(am__v_AR_@AM_V@) +am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@) +am__v_AR_0 = @echo " AR " $@; +am__v_AR_1 = libbcm2835_a_AR = $(AR) $(ARFLAGS) libbcm2835_a_LIBADD = am_libbcm2835_a_OBJECTS = bcm2835.$(OBJEXT) @@ -99,14 +132,34 @@ libbcm2835_a_OBJECTS = $(am_libbcm2835_a_OBJECTS) am_test_OBJECTS = test.$(OBJEXT) test_OBJECTS = $(am_test_OBJECTS) test_DEPENDENCIES = ./libbcm2835.a +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = SOURCES = $(libbcm2835_a_SOURCES) $(test_SOURCES) DIST_SOURCES = $(libbcm2835_a_SOURCES) $(test_SOURCES) am__can_run_installinfo = \ @@ -115,15 +168,206 @@ am__can_run_installinfo = \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(include_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no -am__tty_colors = $(am__tty_colors_dummy) +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red=''; \ + grn=''; \ + lgn=''; \ + blu=''; \ + mgn=''; \ + brg=''; \ + std=''; \ + fi; \ +} +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +RECHECK_LOGS = $(TEST_LOGS) +AM_RECURSIVE_TARGETS = check recheck +TEST_SUITE_LOG = test-suite.log +TEST_EXTENSIONS = @EXEEXT@ .test +LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) +am__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.test.log=.log) +TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ + $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ @@ -217,7 +461,7 @@ CLEANFILES = *~ all: all-am .SUFFIXES: -.SUFFIXES: .c .o .obj +.SUFFIXES: .c .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ @@ -279,16 +523,18 @@ uninstall-libLIBRARIES: clean-libLIBRARIES: -test -z "$(lib_LIBRARIES)" || rm -f $(lib_LIBRARIES) + libbcm2835.a: $(libbcm2835_a_OBJECTS) $(libbcm2835_a_DEPENDENCIES) $(EXTRA_libbcm2835_a_DEPENDENCIES) - -rm -f libbcm2835.a - $(libbcm2835_a_AR) libbcm2835.a $(libbcm2835_a_OBJECTS) $(libbcm2835_a_LIBADD) - $(RANLIB) libbcm2835.a + $(AM_V_at)-rm -f libbcm2835.a + $(AM_V_AR)$(libbcm2835_a_AR) libbcm2835.a $(libbcm2835_a_OBJECTS) $(libbcm2835_a_LIBADD) + $(AM_V_at)$(RANLIB) libbcm2835.a clean-checkPROGRAMS: -test -z "$(check_PROGRAMS)" || rm -f $(check_PROGRAMS) + test$(EXEEXT): $(test_OBJECTS) $(test_DEPENDENCIES) $(EXTRA_test_DEPENDENCIES) @rm -f test$(EXEEXT) - $(LINK) $(test_OBJECTS) $(test_LDADD) $(LIBS) + $(AM_V_CCLD)$(LINK) $(test_OBJECTS) $(test_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -300,18 +546,18 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test.Po@am__quote@ .c.o: -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< .c.obj: -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` install-includeHEADERS: $(include_HEADERS) @$(NORMAL_INSTALL) @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ @@ -334,26 +580,15 @@ uninstall-includeHEADERS: files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir) -ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - mkid -fID $$unique -tags: TAGS - -TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ + $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ @@ -365,15 +600,11 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $$unique; \ fi; \ fi -ctags: CTAGS -CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique @@ -382,9 +613,10 @@ GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am -cscopelist: $(HEADERS) $(SOURCES) $(LISP) - list='$(SOURCES) $(HEADERS) $(LISP)'; \ +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ @@ -400,98 +632,168 @@ cscopelist: $(HEADERS) $(SOURCES) $(LISP) distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -check-TESTS: $(TESTS) - @failed=0; all=0; xfail=0; xpass=0; skip=0; \ - srcdir=$(srcdir); export srcdir; \ - list=' $(TESTS) '; \ - $(am__tty_colors); \ - if test -n "$$list"; then \ - for tst in $$list; do \ - if test -f ./$$tst; then dir=./; \ - elif test -f $$tst; then dir=; \ - else dir="$(srcdir)/"; fi; \ - if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \ - all=`expr $$all + 1`; \ - case " $(XFAIL_TESTS) " in \ - *[\ \ ]$$tst[\ \ ]*) \ - xpass=`expr $$xpass + 1`; \ - failed=`expr $$failed + 1`; \ - col=$$red; res=XPASS; \ - ;; \ - *) \ - col=$$grn; res=PASS; \ - ;; \ - esac; \ - elif test $$? -ne 77; then \ - all=`expr $$all + 1`; \ - case " $(XFAIL_TESTS) " in \ - *[\ \ ]$$tst[\ \ ]*) \ - xfail=`expr $$xfail + 1`; \ - col=$$lgn; res=XFAIL; \ - ;; \ - *) \ - failed=`expr $$failed + 1`; \ - col=$$red; res=FAIL; \ - ;; \ - esac; \ - else \ - skip=`expr $$skip + 1`; \ - col=$$blu; res=SKIP; \ - fi; \ - echo "$${col}$$res$${std}: $$tst"; \ - done; \ - if test "$$all" -eq 1; then \ - tests="test"; \ - All=""; \ - else \ - tests="tests"; \ - All="All "; \ +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ - if test "$$failed" -eq 0; then \ - if test "$$xfail" -eq 0; then \ - banner="$$All$$all $$tests passed"; \ - else \ - if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ - banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ - fi; \ - else \ - if test "$$xpass" -eq 0; then \ - banner="$$failed of $$all $$tests failed"; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + else \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ + done; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ else \ - if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ - banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ - fi; \ - dashes="$$banner"; \ - skipped=""; \ - if test "$$skip" -ne 0; then \ - if test "$$skip" -eq 1; then \ - skipped="($$skip test was not run)"; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ else \ - skipped="($$skip tests were not run)"; \ + color_start= color_end=; \ fi; \ - test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ - dashes="$$skipped"; \ - fi; \ - report=""; \ - if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ - report="Please report to $(PACKAGE_BUGREPORT)"; \ - test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ - dashes="$$report"; \ - fi; \ - dashes=`echo "$$dashes" | sed s/./=/g`; \ - if test "$$failed" -eq 0; then \ - col="$$grn"; \ - else \ - col="$$red"; \ - fi; \ - echo "$${col}$$dashes$${std}"; \ - echo "$${col}$$banner$${std}"; \ - test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \ - test -z "$$report" || echo "$${col}$$report$${std}"; \ - echo "$${col}$$dashes$${std}"; \ - test "$$failed" -eq 0; \ - else :; fi + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 + +check-TESTS: + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all $(check_PROGRAMS) + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +test.log: test$(EXEEXT) + @p='test$(EXEEXT)'; \ + b='test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +.test.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.test$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ @@ -552,6 +854,9 @@ install-strip: "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) @@ -635,19 +940,21 @@ uninstall-am: uninstall-includeHEADERS uninstall-libLIBRARIES .MAKE: check-am install-am install-strip -.PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \ +.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libLIBRARIES \ - cscopelist ctags distclean distclean-compile distclean-generic \ - distclean-tags distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-includeHEADERS install-info \ - install-info-am install-libLIBRARIES install-man install-pdf \ - install-pdf-am install-ps install-ps-am install-strip \ - installcheck installcheck-am installdirs maintainer-clean \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am \ + install-includeHEADERS install-info install-info-am \ + install-libLIBRARIES install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ - uninstall-am uninstall-includeHEADERS uninstall-libLIBRARIES + mostlyclean-generic pdf pdf-am ps ps-am recheck tags tags-am \ + uninstall uninstall-am uninstall-includeHEADERS \ + uninstall-libLIBRARIES # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/src/bcm2835.c b/src/bcm2835.c index 4ee3519..c3dc5c7 100644 --- a/src/bcm2835.c +++ b/src/bcm2835.c @@ -1,12 +1,12 @@ -// bcm2835.c +/* bcm2835.c // C and C++ support for Broadcom BCM 2835 as used in Raspberry Pi // http://elinux.org/RPi_Low-level_peripherals // http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf // // Author: Mike McCauley // Copyright (C) 2011-2013 Mike McCauley -// $Id: bcm2835.c,v 1.14 2013/12/06 22:24:52 mikem Exp mikem $ - +// $Id: bcm2835.c,v 1.23 2015/03/31 04:55:41 mikem Exp mikem $ +*/ #include @@ -17,52 +17,101 @@ #include #include #include +#include - +#define BCK2835_LIBRARY_BUILD #include "bcm2835.h" -// This define enables a little test program (by default a blinking output on pin RPI_GPIO_PIN_11) +/* This define enables a little test program (by default a blinking output on pin RPI_GPIO_PIN_11) // You can do some safe, non-destructive testing on any platform with: // gcc bcm2835.c -D BCM2835_TEST // ./a.out -//#define BCM2835_TEST +*/ +/*#define BCM2835_TEST*/ -// Uncommenting this define compiles alternative I2C code for the version 1 RPi +/* Uncommenting this define compiles alternative I2C code for the version 1 RPi // The P1 header I2C pins are connected to SDA0 and SCL0 on V1. // 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; - - -// This variable allows us to test on hardware other than RPi. +*/ +/* #define I2C_V1*/ + +/* 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 + */ +uint32_t *bcm2835_peripherals = (uint32_t *)MAP_FAILED; + +/* And the register bases within the peripherals block + */ +volatile uint32_t *bcm2835_gpio = (uint32_t *)MAP_FAILED; +volatile uint32_t *bcm2835_pwm = (uint32_t *)MAP_FAILED; +volatile uint32_t *bcm2835_clk = (uint32_t *)MAP_FAILED; +volatile uint32_t *bcm2835_pads = (uint32_t *)MAP_FAILED; +volatile uint32_t *bcm2835_spi0 = (uint32_t *)MAP_FAILED; +volatile uint32_t *bcm2835_bsc0 = (uint32_t *)MAP_FAILED; +volatile uint32_t *bcm2835_bsc1 = (uint32_t *)MAP_FAILED; +volatile 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 // Instead it prints out what it _would_ do if debug were 0 +*/ static uint8_t debug = 0; -// I2C The time needed to transmit one byte. In microseconds. +/* I2C The time needed to transmit one byte. In microseconds. + */ static int i2c_byte_wait_us = 0; -// +/* // 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 +unsigned int bcm2835_version(void) +{ + return BCM2835_VERSION; +} + +/* Read with memory barriers from peripheral + * + */ uint32_t bcm2835_peri_read(volatile uint32_t* paddr) { + uint32_t ret; if (debug) { printf("bcm2835_peri_read paddr %08X\n", (unsigned) paddr); @@ -70,15 +119,19 @@ uint32_t bcm2835_peri_read(volatile uint32_t* paddr) } else { - // Make sure we dont return the _last_ read which might get lost - // if subsequent code changes to a different peripheral - uint32_t ret = *paddr; - *paddr; // Read without assigneing to an unused variable - return ret; + __sync_synchronize(); + ret = *paddr; + __sync_synchronize(); + return ret; } } -// read from peripheral without the read barrier +/* read from peripheral without the read barrier + * This can only be used if more reads to THE SAME peripheral + * will follow. The sequence must terminate with memory barrier + * before any read or write to another peripheral can occur. + * The MB can be explicit, or one of the barrier read/write calls. + */ uint32_t bcm2835_peri_read_nb(volatile uint32_t* paddr) { if (debug) @@ -92,23 +145,24 @@ uint32_t bcm2835_peri_read_nb(volatile uint32_t* paddr) } } -// safe write to peripheral +/* Write with memory barriers to peripheral + */ + void bcm2835_peri_write(volatile uint32_t* paddr, uint32_t value) { - if (debug) + if (debug) { printf("bcm2835_peri_write paddr %08X, value %08X\n", (unsigned) paddr, value); } - else + else { - // Make sure we don't rely on the first write, which may get - // lost if the previous access was to a different peripheral. - *paddr = value; - *paddr = value; + __sync_synchronize(); + *paddr = value; + __sync_synchronize(); } } -// write to peripheral without the write barrier +/* write to peripheral without the write barrier */ void bcm2835_peri_write_nb(volatile uint32_t* paddr, uint32_t value) { if (debug) @@ -122,7 +176,9 @@ void bcm2835_peri_write_nb(volatile uint32_t* paddr, uint32_t value) } } -// Set/clear only the bits in value covered by the mask +/* Set/clear only the bits in value covered by the mask + * This is not atomic - can be interrupted. + */ void bcm2835_peri_set_bits(volatile uint32_t* paddr, uint32_t value, uint32_t mask) { uint32_t v = bcm2835_peri_read(paddr); @@ -130,11 +186,11 @@ void bcm2835_peri_set_bits(volatile uint32_t* paddr, uint32_t value, uint32_t ma bcm2835_peri_write(paddr, v); } -// +/* // Low level convenience functions -// +*/ -// Function select +/* Function select // pin is a BCM2835 GPIO pin number NOT RPi pin number // There are 6 control registers, each control the functions of a block // of 10 pins. @@ -151,9 +207,10 @@ void bcm2835_peri_set_bits(volatile uint32_t* paddr, uint32_t value, uint32_t ma // // So the 3 bits for port X are: // X / 10 + ((X % 10) * 3) +*/ void bcm2835_gpio_fsel(uint8_t pin, uint8_t mode) { - // Function selects are 10 pins per 32 bit word, 3 bits per pin + /* Function selects are 10 pins per 32 bit word, 3 bits per pin */ volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPFSEL0/4 + (pin/10); uint8_t shift = (pin % 10) * 3; uint32_t mask = BCM2835_GPIO_FSEL_MASK << shift; @@ -161,7 +218,7 @@ void bcm2835_gpio_fsel(uint8_t pin, uint8_t mode) bcm2835_peri_set_bits(paddr, value, mask); } -// Set output pin +/* Set output pin */ void bcm2835_gpio_set(uint8_t pin) { volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPSET0/4 + pin/32; @@ -169,7 +226,7 @@ void bcm2835_gpio_set(uint8_t pin) bcm2835_peri_write(paddr, 1 << shift); } -// Clear output pin +/* Clear output pin */ void bcm2835_gpio_clr(uint8_t pin) { volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPCLR0/4 + pin/32; @@ -177,21 +234,21 @@ void bcm2835_gpio_clr(uint8_t pin) bcm2835_peri_write(paddr, 1 << shift); } -// Set all output pins in the mask +/* Set all output pins in the mask */ void bcm2835_gpio_set_multi(uint32_t mask) { volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPSET0/4; bcm2835_peri_write(paddr, mask); } -// Clear all output pins in the 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; bcm2835_peri_write(paddr, mask); } -// Read input pin +/* Read input pin */ uint8_t bcm2835_gpio_lev(uint8_t pin) { volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPLEV0/4 + pin/32; @@ -200,8 +257,9 @@ uint8_t bcm2835_gpio_lev(uint8_t pin) return (value & (1 << shift)) ? HIGH : LOW; } -// See if an event detection bit is set +/* See if an event detection bit is set // Sigh cant support interrupts yet +*/ uint8_t bcm2835_gpio_eds(uint8_t pin) { volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPEDS0/4 + pin/32; @@ -210,7 +268,14 @@ uint8_t bcm2835_gpio_eds(uint8_t pin) return (value & (1 << shift)) ? HIGH : LOW; } -// Write a 1 to clear the bit in EDS +uint32_t bcm2835_gpio_eds_multi(uint32_t mask) +{ + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPEDS0/4; + uint32_t value = bcm2835_peri_read(paddr); + return (value & mask); +} + +/* 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; @@ -219,7 +284,13 @@ void bcm2835_gpio_set_eds(uint8_t pin) bcm2835_peri_write(paddr, value); } -// Rising edge detect enable +void bcm2835_gpio_set_eds_multi(uint32_t mask) +{ + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPEDS0/4; + bcm2835_peri_write(paddr, mask); +} + +/* Rising edge detect enable */ void bcm2835_gpio_ren(uint8_t pin) { volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPREN0/4 + pin/32; @@ -235,7 +306,7 @@ void bcm2835_gpio_clr_ren(uint8_t pin) bcm2835_peri_set_bits(paddr, 0, value); } -// Falling edge detect enable +/* Falling edge detect enable */ void bcm2835_gpio_fen(uint8_t pin) { volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPFEN0/4 + pin/32; @@ -251,7 +322,7 @@ void bcm2835_gpio_clr_fen(uint8_t pin) bcm2835_peri_set_bits(paddr, 0, value); } -// High detect enable +/* High detect enable */ void bcm2835_gpio_hen(uint8_t pin) { volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPHEN0/4 + pin/32; @@ -267,7 +338,7 @@ void bcm2835_gpio_clr_hen(uint8_t pin) bcm2835_peri_set_bits(paddr, 0, value); } -// Low detect enable +/* Low detect enable */ void bcm2835_gpio_len(uint8_t pin) { volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPLEN0/4 + pin/32; @@ -283,7 +354,7 @@ void bcm2835_gpio_clr_len(uint8_t pin) bcm2835_peri_set_bits(paddr, 0, value); } -// Async rising edge detect enable +/* Async rising edge detect enable */ void bcm2835_gpio_aren(uint8_t pin) { volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPAREN0/4 + pin/32; @@ -299,7 +370,7 @@ void bcm2835_gpio_clr_aren(uint8_t pin) bcm2835_peri_set_bits(paddr, 0, value); } -// Async falling edge detect enable +/* Async falling edge detect enable */ void bcm2835_gpio_afen(uint8_t pin) { volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPAFEN0/4 + pin/32; @@ -315,15 +386,16 @@ void bcm2835_gpio_clr_afen(uint8_t pin) bcm2835_peri_set_bits(paddr, 0, value); } -// Set pullup/down +/* Set pullup/down */ void bcm2835_gpio_pud(uint8_t pud) { volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPPUD/4; bcm2835_peri_write(paddr, pud); } -// Pullup/down clock +/* Pullup/down clock // 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; @@ -331,24 +403,32 @@ void bcm2835_gpio_pudclk(uint8_t pin, uint8_t on) bcm2835_peri_write(paddr, (on ? 1 : 0) << shift); } -// Read GPIO pad behaviour for groups of GPIOs +/* 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; + if (bcm2835_pads == MAP_FAILED) + return 0; + + volatile uint32_t* paddr = bcm2835_pads + BCM2835_PADS_GPIO_0_27/4 + group; return bcm2835_peri_read(paddr); } -// Set GPIO pad behaviour for groups of GPIOs -// powerup value for al pads is +/* Set GPIO pad behaviour for groups of GPIOs +// powerup value for all pads is // 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; + if (bcm2835_pads == MAP_FAILED) + return; + + volatile uint32_t* paddr = bcm2835_pads + BCM2835_PADS_GPIO_0_27/4 + group; bcm2835_peri_write(paddr, control | BCM2835_PAD_PASSWRD); } -// Some convenient arduino-like functions +/* Some convenient arduino-like functions // milliseconds +*/ void bcm2835_delay(unsigned int millis) { struct timespec sleeper; @@ -358,14 +438,22 @@ void bcm2835_delay(unsigned int millis) nanosleep(&sleeper, NULL); } -// microseconds +/* microseconds */ void bcm2835_delayMicroseconds(uint64_t micros) { struct timespec t1; uint64_t start; - // Calling nanosleep() takes at least 100-200 us, so use it for + if (debug) + { + /* Cant access sytem timers in debug mode */ + printf("bcm2835_delayMicroseconds %lld\n", micros); + return; + } + + /* 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) @@ -378,11 +466,11 @@ void bcm2835_delayMicroseconds(uint64_t micros) bcm2835_st_delay(start, micros); } -// +/* // Higher level convenience functions -// +*/ -// Set the state of an output +/* Set the state of an output */ void bcm2835_gpio_write(uint8_t pin, uint8_t on) { if (on) @@ -391,7 +479,7 @@ void bcm2835_gpio_write(uint8_t pin, uint8_t on) bcm2835_gpio_clr(pin); } -// Set the state of a all 32 outputs in the mask to on or off +/* Set the state of a all 32 outputs in the mask to on or off */ void bcm2835_gpio_write_multi(uint32_t mask, uint8_t on) { if (on) @@ -400,14 +488,14 @@ void bcm2835_gpio_write_multi(uint32_t mask, uint8_t on) bcm2835_gpio_clr_multi(mask); } -// Set the state of a all 32 outputs in the mask to the values in value +/* Set the state of a all 32 outputs in the mask to the values in value */ void bcm2835_gpio_write_mask(uint32_t value, uint32_t mask) { bcm2835_gpio_set_multi(value & mask); bcm2835_gpio_clr_multi((~value) & mask); } -// Set the pullup/down resistor for a pin +/* Set the pullup/down resistor for a pin // // The GPIO Pull-up/down Clock Registers control the actuation of internal pull-downs on // the respective GPIO pins. These registers must be used in conjunction with the GPPUD @@ -424,6 +512,7 @@ void bcm2835_gpio_write_mask(uint32_t value, uint32_t mask) // 6. Write to GPPUDCLK0/1 to remove the clock // // RPi has P1-03 and P1-05 with 1k8 pullup resistor +*/ void bcm2835_gpio_set_pud(uint8_t pin, uint8_t pud) { bcm2835_gpio_pud(pud); @@ -434,42 +523,50 @@ void bcm2835_gpio_set_pud(uint8_t pin, uint8_t pud) bcm2835_gpio_pudclk(pin, 0); } -void bcm2835_spi_begin(void) +int 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 - 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 + volatile uint32_t* paddr; + + if (bcm2835_spi0 == MAP_FAILED) + return 0; /* bcm2835_init() failed, or not root */ - // 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 + /* 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 */ - // Clear TX and RX fifos + /* Set the SPI CS register to the some sensible defaults */ + 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); + + return 1; // OK } void bcm2835_spi_end(void) { - // 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 + /* 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 */ } -void bcm2835_spi_setBitOrder(uint8_t order) +void bcm2835_spi_setBitOrder(uint8_t __attribute__((unused)) order) { - // BCM2835_SPI_BIT_ORDER_MSBFIRST is the only one suported by SPI0 + /* BCM2835_SPI_BIT_ORDER_MSBFIRST is the only one supported by SPI0 */ } -// defaults to 0, which means a divider of 65536. +/* defaults to 0, which means a divider of 65536. // The divisor must be a power of 2. Odd numbers // rounded down. The maximum SPI clock rate is // of the APB clock +*/ void bcm2835_spi_setClockDivider(uint16_t divider) { volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CLK/4; @@ -479,46 +576,48 @@ void bcm2835_spi_setClockDivider(uint16_t divider) void bcm2835_spi_setDataMode(uint8_t mode) { volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - // Mask in the CPO and CPHA bits of CS + /* Mask in the CPO and CPHA bits of CS */ bcm2835_peri_set_bits(paddr, mode << 2, BCM2835_SPI0_CS_CPOL | BCM2835_SPI0_CS_CPHA); } -// Writes (and reads) a single byte to SPI +/* 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 ret; - // This is Polled transfer as per section 10.6.1 + /* 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? // Clear TX and RX fifos + */ bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR); - // Set TA = 1 + /* Set TA = 1 */ bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA); - // Maybe wait for TXD + /* Maybe wait for TXD */ while (!(bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD)) ; - // Write to FIFO, no barrier + /* Write to FIFO, no barrier */ bcm2835_peri_write_nb(fifo, value); - // Wait for DONE to be set + /* Wait for DONE to be set */ while (!(bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE)) ; - // Read any byte that was sent back by the slave while we sere sending to it - uint32_t ret = bcm2835_peri_read_nb(fifo); + /* Read any byte that was sent back by the slave while we sere sending to it */ + ret = bcm2835_peri_read_nb(fifo); - // Set TA = 0, and also set the barrier + /* Set TA = 0, and also set the barrier */ bcm2835_peri_set_bits(paddr, 0, BCM2835_SPI0_CS_TA); return ret; } -// Writes (and reads) an number of bytes to SPI +/* 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; @@ -526,83 +625,87 @@ void bcm2835_spi_transfernb(char* tbuf, char* rbuf, uint32_t len) uint32_t TXCnt=0; uint32_t RXCnt=0; - // This is Polled transfer as per section 10.6.1 + /* 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? + */ - // Clear TX and RX fifos + /* Clear TX and RX fifos */ bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR); - // Set TA = 1 + /* Set TA = 1 */ bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA); - // Use the FIFO's to reduce the interbyte times + /* Use the FIFO's to reduce the interbyte times */ while((TXCnt < len)||(RXCnt < len)) { - // TX fifo not full, so add some more bytes + /* TX fifo not full, so add some more bytes */ while(((bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD))&&(TXCnt < len )) { bcm2835_peri_write_nb(fifo, tbuf[TXCnt]); TXCnt++; } - //Rx fifo not empty, so get the next received bytes + /* Rx fifo not empty, so get the next received bytes */ while(((bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD))&&( RXCnt < len )) { rbuf[RXCnt] = bcm2835_peri_read_nb(fifo); RXCnt++; } } - // Wait for DONE to be set + /* Wait for DONE to be set */ while (!(bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE)) ; - // Set TA = 0, and also set the barrier + /* 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 +/* 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 i; - // This is Polled transfer as per section 10.6.1 + /* 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? + // Answer: an ISR is required to issue the required memory barriers. + */ - // Clear TX and RX fifos + /* Clear TX and RX fifos */ bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR); - // Set TA = 1 + /* Set TA = 1 */ bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA); - uint32_t i; for (i = 0; i < len; i++) { - // Maybe wait for TXD + /* Maybe wait for TXD */ while (!(bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD)) ; - // Write to FIFO, no barrier + /* Write to FIFO, no barrier */ bcm2835_peri_write_nb(fifo, tbuf[i]); - // Read from FIFO to prevent stalling + /* 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 + /* 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) (void) bcm2835_peri_read_nb(fifo); }; - // Set TA = 0, and also set the barrier + /* Set TA = 0, and also set the barrier */ bcm2835_peri_set_bits(paddr, 0, BCM2835_SPI0_CS_TA); } -// Writes (and reads) an number of bytes to SPI +/* Writes (and reads) an number of bytes to SPI // Read bytes are copied over onto the transmit buffer +*/ void bcm2835_spi_transfern(char* buf, uint32_t len) { bcm2835_spi_transfernb(buf, buf, len); @@ -611,7 +714,7 @@ 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; - // Mask in the CS bits of CS + /* Mask in the CS bits of CS */ bcm2835_peri_set_bits(paddr, cs, BCM2835_SPI0_CS_CS); } @@ -619,59 +722,69 @@ void bcm2835_spi_setChipSelectPolarity(uint8_t cs, uint8_t active) { volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; uint8_t shift = 21 + cs; - // Mask in the appropriate CSPOLn bit + /* Mask in the appropriate CSPOLn bit */ bcm2835_peri_set_bits(paddr, active << shift, 1 << shift); } -void bcm2835_i2c_begin(void) +int bcm2835_i2c_begin(void) { + uint16_t cdiv; + + if ( bcm2835_bsc0 == MAP_FAILED + || bcm2835_bsc1 == MAP_FAILED) + return 0; /* bcm2835_init() failed, or not root */ + #ifdef I2C_V1 volatile 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 + /* 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; - // 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 + /* 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 - // Read the clock divider register - uint16_t cdiv = bcm2835_peri_read(paddr); - // Calculate time for transmitting one byte + /* Read the clock divider register */ + cdiv = bcm2835_peri_read(paddr); + /* Calculate time for transmitting one byte // 1000000 = micros seconds in a second // 9 = Clocks per byte : 8 bits + ACK + */ i2c_byte_wait_us = ((float)cdiv / BCM2835_CORE_CLK_HZ) * 1000000 * 9; + + return 1; } void bcm2835_i2c_end(void) { #ifdef I2C_V1 - // Set all the I2C/BSC0 pins back to input - bcm2835_gpio_fsel(RPI_GPIO_P1_03, BCM2835_GPIO_FSEL_INPT); // SDA - bcm2835_gpio_fsel(RPI_GPIO_P1_05, BCM2835_GPIO_FSEL_INPT); // SCL + /* Set all the I2C/BSC0 pins back to input */ + bcm2835_gpio_fsel(RPI_GPIO_P1_03, BCM2835_GPIO_FSEL_INPT); /* SDA */ + bcm2835_gpio_fsel(RPI_GPIO_P1_05, BCM2835_GPIO_FSEL_INPT); /* SCL */ #else - // Set all the I2C/BSC1 pins back to input - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_03, BCM2835_GPIO_FSEL_INPT); // SDA - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_05, BCM2835_GPIO_FSEL_INPT); // SCL + /* Set all the I2C/BSC1 pins back to input */ + bcm2835_gpio_fsel(RPI_V2_GPIO_P1_03, BCM2835_GPIO_FSEL_INPT); /* SDA */ + bcm2835_gpio_fsel(RPI_V2_GPIO_P1_05, BCM2835_GPIO_FSEL_INPT); /* SCL */ #endif } void bcm2835_i2c_setSlaveAddress(uint8_t addr) { - // Set I2C Device Address + /* Set I2C Device Address */ #ifdef I2C_V1 - volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_A/4; + volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_A/4; #else - volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_A/4; + volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_A/4; #endif - bcm2835_peri_write(paddr, addr); + bcm2835_peri_write(paddr, addr); } -// defaults to 0x5dc, should result in a 166.666 kHz I2C clock frequency. +/* defaults to 0x5dc, should result in a 166.666 kHz I2C clock frequency. // The divisor must be a power of 2. Odd numbers // rounded down. +*/ void bcm2835_i2c_setClockDivider(uint16_t divider) { #ifdef I2C_V1 @@ -680,22 +793,23 @@ void bcm2835_i2c_setClockDivider(uint16_t divider) volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_DIV/4; #endif bcm2835_peri_write(paddr, divider); - // Calculate time for transmitting one byte + /* Calculate time for transmitting one byte // 1000000 = micros seconds in a second // 9 = Clocks per byte : 8 bits + ACK + */ i2c_byte_wait_us = ((float)divider / BCM2835_CORE_CLK_HZ) * 1000000 * 9; } -// set I2C clock divider by means of a baudrate number +/* set I2C clock divider by means of a baudrate number */ void bcm2835_i2c_set_baudrate(uint32_t baudrate) { uint32_t divider; - // use 0xFFFE mask to limit a max value and round down any odd number + /* use 0xFFFE mask to limit a max value and round down any odd number */ divider = (BCM2835_CORE_CLK_HZ / baudrate) & 0xFFFE; bcm2835_i2c_setClockDivider( (uint16_t)divider ); } -// Writes an number of bytes to I2C +/* Writes an number of bytes to I2C */ uint8_t bcm2835_i2c_write(const char * buf, uint32_t len) { #ifdef I2C_V1 @@ -714,13 +828,13 @@ uint8_t bcm2835_i2c_write(const char * buf, uint32_t len) uint32_t i = 0; uint8_t reason = BCM2835_I2C_REASON_OK; - // Clear FIFO + /* Clear FIFO */ bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 ); - // Clear Status - bcm2835_peri_write_nb(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE); - // Set Data Length - bcm2835_peri_write_nb(dlen, len); - // pre populate FIFO with max buffer + /* Clear Status */ + bcm2835_peri_write(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE); + /* Set Data Length */ + bcm2835_peri_write(dlen, len); + /* pre populate FIFO with max buffer */ while( remaining && ( i < BCM2835_BSC_FIFO_SIZE ) ) { bcm2835_peri_write_nb(fifo, buf[i]); @@ -728,37 +842,37 @@ uint8_t bcm2835_i2c_write(const char * buf, uint32_t len) remaining--; } - // Enable device and start transfer - bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST); + /* Enable device and start transfer */ + bcm2835_peri_write(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 )) + /* Transfer is over when BCM2835_BSC_S_DONE */ + while(!(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE )) { - while ( remaining && (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_TXD )) + while ( remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_TXD )) { - // Write to FIFO, no barrier - bcm2835_peri_write_nb(fifo, buf[i]); - i++; - remaining--; + /* Write to FIFO */ + bcm2835_peri_write(fifo, buf[i]); + i++; + remaining--; } } - // Received a NACK + /* Received a NACK */ if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) { - reason = BCM2835_I2C_REASON_ERROR_NACK; + reason = BCM2835_I2C_REASON_ERROR_NACK; } - // Received Clock Stretch Timeout + /* Received Clock Stretch Timeout */ else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) { - reason = BCM2835_I2C_REASON_ERROR_CLKT; + reason = BCM2835_I2C_REASON_ERROR_CLKT; } - // Not all data is sent + /* Not all data is sent */ else if (remaining) { - reason = BCM2835_I2C_REASON_ERROR_DATA; + reason = BCM2835_I2C_REASON_ERROR_DATA; } bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE , BCM2835_BSC_S_DONE); @@ -766,7 +880,7 @@ uint8_t bcm2835_i2c_write(const char * buf, uint32_t len) return reason; } -// Read an number of bytes from I2C +/* Read an number of bytes from I2C */ uint8_t bcm2835_i2c_read(char* buf, uint32_t len) { #ifdef I2C_V1 @@ -785,53 +899,53 @@ uint8_t bcm2835_i2c_read(char* buf, uint32_t len) uint32_t i = 0; uint8_t reason = BCM2835_I2C_REASON_OK; - // Clear FIFO + /* Clear FIFO */ bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 ); - // Clear Status - bcm2835_peri_write_nb(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE); - // Set Data Length + /* Clear Status */ + bcm2835_peri_write_nb(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE); + /* Set Data Length */ bcm2835_peri_write_nb(dlen, len); - // Start read + /* Start read */ bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ); - // wait for transfer to complete + /* wait for transfer to complete */ while (!(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE)) { - // we must empty the FIFO as it is populated and not use any delay + /* we must empty the FIFO as it is populated and not use any delay */ while (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD) { - // Read from FIFO, no barrier - buf[i] = bcm2835_peri_read_nb(fifo); - i++; - remaining--; + /* Read from FIFO, no barrier */ + buf[i] = bcm2835_peri_read_nb(fifo); + i++; + remaining--; } } - // transfer has finished - grab any remaining stuff in FIFO + /* transfer has finished - grab any remaining stuff in FIFO */ while (remaining && (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD)) { - // Read from FIFO, no barrier + /* Read from FIFO, no barrier */ buf[i] = bcm2835_peri_read_nb(fifo); i++; remaining--; } - // Received a NACK + /* Received a NACK */ if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) { - reason = BCM2835_I2C_REASON_ERROR_NACK; + reason = BCM2835_I2C_REASON_ERROR_NACK; } - // Received Clock Stretch Timeout + /* Received Clock Stretch Timeout */ else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) { - reason = BCM2835_I2C_REASON_ERROR_CLKT; + reason = BCM2835_I2C_REASON_ERROR_CLKT; } - // Not all data is received + /* Not all data is received */ else if (remaining) { - reason = BCM2835_I2C_REASON_ERROR_DATA; + reason = BCM2835_I2C_REASON_ERROR_DATA; } bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE , BCM2835_BSC_S_DONE); @@ -839,8 +953,9 @@ uint8_t bcm2835_i2c_read(char* buf, uint32_t len) return reason; } -// Read an number of bytes from I2C sending a repeated start after writing +/* 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 @@ -858,70 +973,70 @@ uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len) uint32_t i = 0; uint8_t reason = BCM2835_I2C_REASON_OK; - // Clear FIFO + /* Clear FIFO */ bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 ); - // Clear Status - bcm2835_peri_write_nb(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE); - // Set Data Length - bcm2835_peri_write_nb(dlen, 1); - // Enable device and start transfer - 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); + /* Clear Status */ + bcm2835_peri_write(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE); + /* Set Data Length */ + bcm2835_peri_write(dlen, 1); + /* Enable device and start transfer */ + bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN); + bcm2835_peri_write(fifo, regaddr[0]); + bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST); - // poll for transfer has started - while ( !( bcm2835_peri_read_nb(status) & BCM2835_BSC_S_TA ) ) + /* poll for transfer has started */ + while ( !( bcm2835_peri_read(status) & BCM2835_BSC_S_TA ) ) { - // Linux may cause us to miss entire transfer stage + /* Linux may cause us to miss entire transfer stage */ 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 ); + /* Send a repeated start with read bit set in address */ + bcm2835_peri_write(dlen, len); + bcm2835_peri_write(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)) + /* wait for transfer to complete */ + while (!(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE)) { - // we must empty the FIFO as it is populated and not use any delay - while (remaining && bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD) + /* we must empty the FIFO as it is populated and not use any delay */ + while (remaining && bcm2835_peri_read(status) & BCM2835_BSC_S_RXD) { - // Read from FIFO, no barrier - buf[i] = bcm2835_peri_read_nb(fifo); - i++; - remaining--; + /* Read from FIFO */ + buf[i] = bcm2835_peri_read(fifo); + i++; + remaining--; } } - // transfer has finished - grab any remaining stuff in FIFO - while (remaining && (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD)) + /* transfer has finished - grab any remaining stuff in FIFO */ + while (remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_RXD)) { - // Read from FIFO, no barrier - buf[i] = bcm2835_peri_read_nb(fifo); + /* Read from FIFO */ + buf[i] = bcm2835_peri_read(fifo); i++; remaining--; } - // Received a NACK + /* Received a NACK */ if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) { reason = BCM2835_I2C_REASON_ERROR_NACK; } - // Received Clock Stretch Timeout + /* Received Clock Stretch Timeout */ else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) { - reason = BCM2835_I2C_REASON_ERROR_CLKT; + reason = BCM2835_I2C_REASON_ERROR_CLKT; } - // Not all data is sent + /* Not all data is sent */ else if (remaining) { - reason = BCM2835_I2C_REASON_ERROR_DATA; + reason = BCM2835_I2C_REASON_ERROR_DATA; } bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE , BCM2835_BSC_S_DONE); @@ -929,8 +1044,9 @@ 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 @@ -949,16 +1065,16 @@ uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint uint32_t i = 0; uint8_t reason = BCM2835_I2C_REASON_OK; - // Clear FIFO + /* Clear FIFO */ bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 ); - // Clear Status - bcm2835_peri_write_nb(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE); + /* Clear Status */ + bcm2835_peri_write(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE); - // Set Data Length - bcm2835_peri_write_nb(dlen, cmds_len); + /* Set Data Length */ + bcm2835_peri_write(dlen, cmds_len); - // pre populate FIFO with max buffer + /* pre populate FIFO with max buffer */ while( remaining && ( i < BCM2835_BSC_FIFO_SIZE ) ) { bcm2835_peri_write_nb(fifo, cmds[i]); @@ -966,65 +1082,65 @@ uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint remaining--; } - // Enable device and start transfer - bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST); + /* Enable device and start transfer */ + bcm2835_peri_write(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 ) ) + /* poll for transfer has started (way to do repeated start, from BCM2835 datasheet) */ + while ( !( bcm2835_peri_read(status) & BCM2835_BSC_S_TA ) ) { - // Linux may cause us to miss entire transfer stage - if(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE) + /* Linux may cause us to miss entire transfer stage */ + if(bcm2835_peri_read_nb(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 ); + /* Send a repeated start with read bit set in address */ + bcm2835_peri_write(dlen, buf_len); + bcm2835_peri_write(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 + /* wait for transfer to complete */ while (!(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE)) { - // we must empty the FIFO as it is populated and not use any delay - while (remaining && bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD) + /* we must empty the FIFO as it is populated and not use any delay */ + while (remaining && bcm2835_peri_read(status) & BCM2835_BSC_S_RXD) { - // Read from FIFO, no barrier - buf[i] = bcm2835_peri_read_nb(fifo); - i++; - remaining--; + /* Read from FIFO, no barrier */ + buf[i] = bcm2835_peri_read_nb(fifo); + i++; + remaining--; } } - // transfer has finished - grab any remaining stuff in FIFO - while (remaining && (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD)) + /* transfer has finished - grab any remaining stuff in FIFO */ + while (remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_RXD)) { - // Read from FIFO, no barrier - buf[i] = bcm2835_peri_read_nb(fifo); + /* Read from FIFO */ + buf[i] = bcm2835_peri_read(fifo); i++; remaining--; } - // Received a NACK + /* Received a NACK */ if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) { - reason = BCM2835_I2C_REASON_ERROR_NACK; + reason = BCM2835_I2C_REASON_ERROR_NACK; } - // Received Clock Stretch Timeout + /* Received Clock Stretch Timeout */ else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) { - reason = BCM2835_I2C_REASON_ERROR_CLKT; + reason = BCM2835_I2C_REASON_ERROR_CLKT; } - // Not all data is sent + /* Not all data is sent */ else if (remaining) { - reason = BCM2835_I2C_REASON_ERROR_DATA; + reason = BCM2835_I2C_REASON_ERROR_DATA; } bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE , BCM2835_BSC_S_DONE); @@ -1032,20 +1148,37 @@ uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint return reason; } -// Read the System Timer Counter (64-bits) +/* Read the System Timer Counter (64-bits) */ uint64_t bcm2835_st_read(void) { volatile uint32_t* paddr; + uint32_t hi, lo; uint64_t st; paddr = bcm2835_st + BCM2835_ST_CHI/4; - st = bcm2835_peri_read(paddr); - st <<= 32; + hi = bcm2835_peri_read(paddr); + paddr = bcm2835_st + BCM2835_ST_CLO/4; - st += bcm2835_peri_read(paddr); + lo = bcm2835_peri_read(paddr); + + paddr = bcm2835_st + BCM2835_ST_CHI/4; + st = bcm2835_peri_read(paddr); + + /* Test for overflow */ + if (st == hi) + { + st <<= 32; + st += lo; + } + else + { + st <<= 32; + paddr = bcm2835_st + BCM2835_ST_CLO/4; + st += bcm2835_peri_read(paddr); + } return st; } -// Delays for the specified number of microseconds with offset +/* Delays for the specified number of microseconds with offset */ void bcm2835_st_delay(uint64_t offset_micros, uint64_t micros) { uint64_t compare = offset_micros + micros; @@ -1054,25 +1187,33 @@ void bcm2835_st_delay(uint64_t offset_micros, uint64_t micros) ; } -// PWM +/* PWM */ void bcm2835_pwm_set_clock(uint32_t divisor) { - // From Gerts code - divisor &= 0xfff; - // Stop PWM clock - bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_CNTL, BCM2835_PWM_PASSWRD | 0x01); - 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); - // 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 + if ( bcm2835_clk == MAP_FAILED + || bcm2835_pwm == MAP_FAILED) + return; /* bcm2835_init() failed or not root */ + + /* From Gerts code */ + divisor &= 0xfff; + /* Stop PWM clock */ + bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_CNTL, BCM2835_PWM_PASSWRD | 0x01); + 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); + /* 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 */ } void bcm2835_pwm_set_mode(uint8_t channel, uint8_t markspace, uint8_t enabled) { + if ( bcm2835_clk == MAP_FAILED + || bcm2835_pwm == MAP_FAILED) + return; /* bcm2835_init() failed or not root */ + uint32_t control = bcm2835_peri_read(bcm2835_pwm + BCM2835_PWM_CONTROL); if (channel == 0) @@ -1098,14 +1239,18 @@ void bcm2835_pwm_set_mode(uint8_t channel, uint8_t markspace, uint8_t enabled) control &= ~BCM2835_PWM1_ENABLE; } - // If you use the barrier here, wierd things happen, and the commands dont work + /* If you use the barrier here, wierd things happen, and the commands dont work */ bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM_CONTROL, control); - // bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM_CONTROL, BCM2835_PWM0_ENABLE | BCM2835_PWM1_ENABLE | BCM2835_PWM0_MS_MODE | BCM2835_PWM1_MS_MODE); + /* bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM_CONTROL, BCM2835_PWM0_ENABLE | BCM2835_PWM1_ENABLE | BCM2835_PWM0_MS_MODE | BCM2835_PWM1_MS_MODE); */ } void bcm2835_pwm_set_range(uint8_t channel, uint32_t range) { + if ( bcm2835_clk == MAP_FAILED + || bcm2835_pwm == MAP_FAILED) + return; /* bcm2835_init() failed or not root */ + if (channel == 0) bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM0_RANGE, range); else if (channel == 1) @@ -1114,13 +1259,17 @@ void bcm2835_pwm_set_range(uint8_t channel, uint32_t range) void bcm2835_pwm_set_data(uint8_t channel, uint32_t data) { + if ( bcm2835_clk == MAP_FAILED + || bcm2835_pwm == MAP_FAILED) + return; /* bcm2835_init() failed or not root */ + if (channel == 0) bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM0_DATA, data); else if (channel == 1) bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM1_DATA, data); } -// Allocate page-aligned memory. +/* Allocate page-aligned memory. */ void *malloc_aligned(size_t size) { void *mem; @@ -1128,13 +1277,14 @@ void *malloc_aligned(size_t size) return (errno ? NULL : mem); } -// Map 'size' bytes starting at 'off' in file 'fd' to memory. +/* Map 'size' bytes starting at 'off' in file 'fd' to memory. // Return mapped address on success, MAP_FAILED otherwise. // On error print message. +*/ 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; } @@ -1146,61 +1296,98 @@ static void unmapmem(void **pmem, size_t size) *pmem = MAP_FAILED; } -// Initialise this library. +/* Initialise this library. */ int bcm2835_init(void) { + int memfd; + int ok; + FILE *fp; + 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; - return 1; // Success + bcm2835_peripherals = (uint32_t*)BCM2835_PERI_BASE; + + bcm2835_pads = bcm2835_peripherals + BCM2835_GPIO_PADS/4; + bcm2835_clk = bcm2835_peripherals + BCM2835_CLOCK_BASE/4; + bcm2835_gpio = bcm2835_peripherals + BCM2835_GPIO_BASE/4; + bcm2835_pwm = bcm2835_peripherals + BCM2835_GPIO_PWM/4; + bcm2835_spi0 = bcm2835_peripherals + BCM2835_SPI0_BASE/4; + bcm2835_bsc0 = bcm2835_peripherals + BCM2835_BSC0_BASE/4; + bcm2835_bsc1 = bcm2835_peripherals + BCM2835_BSC1_BASE/4; + bcm2835_st = bcm2835_peripherals + BCM2835_ST_BASE/4; + return 1; /* Success */ } - int memfd = -1; - int ok = 0; - // Open the master /dev/memory device - if ((memfd = open("/dev/mem", O_RDWR | O_SYNC) ) < 0) + + /* Figure out the base and size of the peripheral address block + // using the device-tree. Required for RPi2, optional for RPi 1 + */ + if ((fp = fopen(BMC2835_RPI2_DT_FILENAME , "rb"))) { - fprintf(stderr, "bcm2835_init: Unable to open /dev/mem: %s\n", - strerror(errno)) ; - goto exit; + 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 + * If we are not root, try for the new /dev/gpiomem interface and accept + * the fact that we can only access GPIO + * else try for the /dev/mem interface and get access to everything + */ + memfd = -1; + ok = 0; + if (geteuid() == 0) + { + /* Open the master /dev/mem device */ + 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; + } + + /* Base of the peripherals block is mapped to VM */ + bcm2835_peripherals = 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 + // Caution: bcm2835_peripherals is uint32_t*, so divide offsets by 4 + */ + bcm2835_gpio = bcm2835_peripherals + BCM2835_GPIO_BASE/4; + bcm2835_pwm = bcm2835_peripherals + BCM2835_GPIO_PWM/4; + bcm2835_clk = bcm2835_peripherals + BCM2835_CLOCK_BASE/4; + bcm2835_pads = bcm2835_peripherals + BCM2835_GPIO_PADS/4; + bcm2835_spi0 = bcm2835_peripherals + BCM2835_SPI0_BASE/4; + bcm2835_bsc0 = bcm2835_peripherals + BCM2835_BSC0_BASE/4; /* I2C */ + bcm2835_bsc1 = bcm2835_peripherals + BCM2835_BSC1_BASE/4; /* I2C */ + bcm2835_st = bcm2835_peripherals + BCM2835_ST_BASE/4; + + ok = 1; + } + else + { + /* Not root, try /dev/gpiomem */ + /* Open the master /dev/mem device */ + if ((memfd = open("/dev/gpiomem", O_RDWR | O_SYNC) ) < 0) + { + fprintf(stderr, "bcm2835_init: Unable to open /dev/gpiomem: %s\n", + strerror(errno)) ; + goto exit; + } + + /* Base of the peripherals block is mapped to VM */ + bcm2835_peripherals_base = 0; + bcm2835_peripherals = mapmem("gpio", bcm2835_peripherals_size, memfd, (uint32_t)bcm2835_peripherals_base); + if (bcm2835_peripherals == MAP_FAILED) goto exit; + bcm2835_gpio = bcm2835_peripherals; + ok = 1; } - - // 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; - - ok = 1; exit: if (memfd >= 0) @@ -1212,88 +1399,94 @@ int bcm2835_init(void) return ok; } -// Close this library and deallocate everything +/* Close this library and deallocate everything */ 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); - return 1; // Success + if (debug) return 1; /* Success */ + + 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 */ } #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) { - // Be non-destructive + /* Be non-destructive */ bcm2835_set_debug(1); if (!bcm2835_init()) return 1; - // Configure some GPIO pins fo some testing + /* Configure some GPIO pins fo some testing // Set RPI pin P1-11 to be an output + */ bcm2835_gpio_fsel(RPI_GPIO_P1_11, BCM2835_GPIO_FSEL_OUTP); - // Set RPI pin P1-15 to be an input + /* Set RPI pin P1-15 to be an input */ bcm2835_gpio_fsel(RPI_GPIO_P1_15, BCM2835_GPIO_FSEL_INPT); - // with a pullup + /* with a pullup */ bcm2835_gpio_set_pud(RPI_GPIO_P1_15, BCM2835_GPIO_PUD_UP); - // And a low detect enable + /* And a low detect enable */ bcm2835_gpio_len(RPI_GPIO_P1_15); - // and input hysteresis disabled on GPIOs 0 to 27 + /* and input hysteresis disabled on GPIOs 0 to 27 */ bcm2835_gpio_set_pad(BCM2835_PAD_GROUP_GPIO_0_27, BCM2835_PAD_SLEW_RATE_UNLIMITED|BCM2835_PAD_DRIVE_8mA); #if 1 - // Blink + /* Blink */ while (1) { - // Turn it on + /* Turn it on */ bcm2835_gpio_write(RPI_GPIO_P1_11, HIGH); - // wait a bit + /* wait a bit */ bcm2835_delay(500); - // turn it off + /* turn it off */ bcm2835_gpio_write(RPI_GPIO_P1_11, LOW); - // wait a bit + /* wait a bit */ bcm2835_delay(500); } #endif #if 0 - // Read input + /* Read input */ while (1) { - // Read some data + /* Read some data */ uint8_t value = bcm2835_gpio_lev(RPI_GPIO_P1_15); printf("read from pin 15: %d\n", value); - // wait a bit + /* wait a bit */ bcm2835_delay(500); } #endif #if 0 - // Look for a low event detection + /* Look for a low event detection // eds will be set whenever pin 15 goes low + */ while (1) { if (bcm2835_gpio_eds(RPI_GPIO_P1_15)) { - // Now clear the eds flag by setting it to 1 + /* Now clear the eds flag by setting it to 1 */ bcm2835_gpio_set_eds(RPI_GPIO_P1_15); printf("low event detect for pin 15\n"); } - // wait a bit + /* wait a bit */ bcm2835_delay(500); } #endif diff --git a/src/bcm2835.h b/src/bcm2835.h index 26f3c09..d92a8a2 100644 --- a/src/bcm2835.h +++ b/src/bcm2835.h @@ -1,703 +1,960 @@ -// bcm2835.h -// -// C and C++ support for Broadcom BCM 2835 as used in Raspberry Pi -// -// Author: Mike McCauley -// Copyright (C) 2011-2013 Mike McCauley -// $Id: bcm2835.h,v 1.13 2013/12/06 22:24:52 mikem Exp mikem $ -// -/// \mainpage C library for Broadcom BCM 2835 as used in Raspberry Pi -/// -/// This is a C library for Raspberry Pi (RPi). It provides access to -/// GPIO and other IO functions on the Broadcom BCM 2835 chip, -/// allowing access to the GPIO pins on the -/// 26 pin IDE plug on the RPi board so you can control and interface with various external devices. -/// -/// It provides functions for reading digital inputs and setting digital outputs, using SPI and I2C, -/// and for accessing the system timers. -/// Pin event detection is supported by polling (interrupts are not supported). -/// -/// It is C++ compatible, and installs as a header file and non-shared library on -/// any Linux-based distro (but clearly is no use except on Raspberry Pi or another board with -/// BCM 2835). -/// -/// The version of the package that this documentation refers to can be downloaded -/// from http://www.airspayce.com/mikem/bcm2835/bcm2835-1.36.tar.gz -/// You can find the latest version at http://www.airspayce.com/mikem/bcm2835 -/// -/// Several example programs are provided. -/// -/// Based on data in http://elinux.org/RPi_Low-level_peripherals and -/// http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf -/// and http://www.scribd.com/doc/101830961/GPIO-Pads-Control2 -/// -/// You can also find online help and discussion at http://groups.google.com/group/bcm2835 -/// Please use that group for all questions and discussions on this topic. -/// Do not contact the author directly, unless it is to discuss commercial licensing. -/// -/// Tested on debian6-19-04-2012, 2012-07-15-wheezy-raspbian, 2013-07-26-wheezy-raspbian -/// and Occidentalisv01 -/// CAUTION: it has been observed that when detect enables such as bcm2835_gpio_len() -/// are used and the pin is pulled LOW -/// it can cause temporary hangs on 2012-07-15-wheezy-raspbian, 2013-07-26-wheezy-raspbian -/// and Occidentalisv01. -/// Reason for this is not yet determined, but we suspect that an interrupt handler is -/// hitting a hard loop on those OSs. -/// If you must use bcm2835_gpio_len() and friends, make sure you disable the pins with -/// bcm2835_gpio_clr_len() and friends after use. -/// -/// \par Installation -/// -/// This library consists of a single non-shared library and header file, which will be -/// installed in the usual places by make install -/// -/// \code -/// # download the latest version of the library, say bcm2835-1.xx.tar.gz, then: -/// tar zxvf bcm2835-1.xx.tar.gz -/// cd bcm2835-1.xx -/// ./configure -/// make -/// sudo make check -/// sudo make install -/// \endcode -/// -/// \par Physical Addresses -/// -/// The functions bcm2835_peri_read(), bcm2835_peri_write() and bcm2835_peri_set_bits() -/// are low level peripheral register access functions. They are designed to use -/// physical addresses as described in section 1.2.3 ARM physical addresses -/// of the BCM2835 ARM Peripherals manual. -/// Physical addresses range from 0x20000000 to 0x20FFFFFF for peripherals. The bus -/// addresses for peripherals are set up to map onto the peripheral bus address range starting at -/// 0x7E000000. Thus a peripheral advertised in the manual at bus address 0x7Ennnnnn is available at -/// physical address 0x20nnnnnn. -/// -/// The base address of the various peripheral registers are available with the following -/// externals: -/// bcm2835_gpio -/// bcm2835_pwm -/// bcm2835_clk -/// bcm2835_pads -/// bcm2835_spio0 -/// bcm2835_st -/// bcm2835_bsc0 -/// bcm2835_bsc1 -/// -/// \par Pin Numbering -/// -/// The GPIO pin numbering as used by RPi is different to and inconsistent with the underlying -/// BCM 2835 chip pin numbering. http://elinux.org/RPi_BCM2835_GPIOs -/// -/// RPi has a 26 pin IDE header that provides access to some of the GPIO pins on the BCM 2835, -/// as well as power and ground pins. Not all GPIO pins on the BCM 2835 are available on the -/// IDE header. -/// -/// RPi Version 2 also has a P5 connector with 4 GPIO pins, 5V, 3.3V and Gnd. -/// -/// The functions in this library are designed to be passed the BCM 2835 GPIO pin number and _not_ -/// the RPi pin number. There are symbolic definitions for each of the available pins -/// that you should use for convenience. See \ref RPiGPIOPin. -/// -/// \par SPI Pins -/// -/// The bcm2835_spi_* functions allow you to control the BCM 2835 SPI0 interface, -/// allowing you to send and received data by SPI (Serial Peripheral Interface). -/// For more information about SPI, see http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus -/// -/// When bcm2835_spi_begin() is called it changes the bahaviour of the SPI interface pins from their -/// default GPIO behaviour in order to support SPI. While SPI is in use, you will not be able -/// to control the state of the SPI pins through the usual bcm2835_spi_gpio_write(). -/// When bcm2835_spi_end() is called, the SPI pins will all revert to inputs, and can then be -/// configured and controled with the usual bcm2835_gpio_* calls. -/// -/// The Raspberry Pi GPIO pins used for SPI are: -/// -/// - P1-19 (MOSI) -/// - P1-21 (MISO) -/// - P1-23 (CLK) -/// - P1-24 (CE0) -/// - P1-26 (CE1) -/// -/// \par I2C Pins -/// -/// The bcm2835_i2c_* functions allow you to control the BCM 2835 BSC interface, -/// allowing you to send and received data by I2C ("eye-squared cee"; generically referred to as "two-wire interface") . -/// For more information about I?C, see http://en.wikipedia.org/wiki/I%C2%B2C -/// -/// The Raspberry Pi V2 GPIO pins used for I2C are: -/// -/// - P1-03 (SDA) -/// - P1-05 (SLC) -/// -/// \par PWM -/// -/// The BCM2835 supports hardware PWM on a limited subset of GPIO pins. This bcm2835 library provides -/// functions for configuring and controlling PWM output on these pins. -/// -/// The BCM2835 contains 2 independent PWM channels (0 and 1), each of which be connnected to a limited subset of -/// GPIO pins. The following GPIO pins may be connected to the following PWM channels (from section 9.5): -/// \code -/// GPIO PIN RPi pin PWM Channel ALT FUN -/// 12 0 0 -/// 13 1 0 -/// 18 1-12 0 5 -/// 19 1 5 -/// 40 0 0 -/// 41 1 0 -/// 45 1 0 -/// 52 0 1 -/// 53 1 1 -/// \endcode -/// In order for a GPIO pin to emit output from its PWM channel, it must be set to the Alt Function given above. -/// Note carefully that current versions of the Raspberry Pi only expose one of these pins (GPIO 18 = RPi Pin 1-12) -/// on the IO headers, and therefore this is the only IO pin on the RPi that can be used for PWM. -/// Further it must be set to ALT FUN 5 to get PWM output. -/// -/// Both PWM channels are driven by the same PWM clock, whose clock dvider can be varied using -/// bcm2835_pwm_set_clock(). Each channel can be separately enabled with bcm2835_pwm_set_mode(). -/// The average output of the PWM channel is determined by the ratio of DATA/RANGE for that channel. -/// Use bcm2835_pwm_set_range() to set the range and bcm2835_pwm_set_data() to set the data in that ratio -/// -/// Each PWM channel can run in either Balanced or Mark-Space mode. In Balanced mode, the hardware -/// sends a combination of clock pulses that results in an overall DATA pulses per RANGE pulses. -/// In Mark-Space mode, the hardware sets the output HIGH for DATA clock pulses wide, followed by -/// LOW for RANGE-DATA clock pulses. -/// -/// The PWM clock can be set to control the PWM pulse widths. The PWM clock is derived from -/// a 19.2MHz clock. You can set any divider, but some common ones are provided by the BCM2835_PWM_CLOCK_DIVIDER_* -/// values of \ref bcm2835PWMClockDivider. -/// -/// For example, say you wanted to drive a DC motor with PWM at about 1kHz, -/// and control the speed in 1/1024 increments from -/// 0/1024 (stopped) through to 1024/1024 (full on). In that case you might set the -/// clock divider to be 16, and the RANGE to 1024. The pulse repetition frequency will be -/// 1.2MHz/1024 = 1171.875Hz. -/// -/// \par Real Time performance constraints -/// -/// The bcm2835 is a library for user programs (i.e. they run in 'userland'). -/// Such programs are not part of the kernel and are usually -/// subject to paging and swapping by the kernel while it does other things besides running your program. -/// This means that you should not expect to get real-time performance or -/// real-time timing constraints from such programs. In particular, there is no guarantee that the -/// bcm2835_delay() and bcm2835_delayMicroseconds() will return after exactly the time requested. -/// In fact, depending on other activity on the host, IO etc, you might get significantly longer delay times -/// than the one you asked for. So please dont expect to get exactly the time delay you request. -/// -/// Arjan reports that you can prevent swapping on Linux with the following code fragment: -/// -/// \code -/// struct sched_param sp; -/// memset(&sp, 0, sizeof(sp)); -/// sp.sched_priority = sched_get_priority_max(SCHED_FIFO); -/// sched_setscheduler(0, SCHED_FIFO, &sp); -/// mlockall(MCL_CURRENT | MCL_FUTURE); -/// \endcode -/// -/// \par Bindings to other languages -/// -/// mikem has made Perl bindings available at CPAN: -/// http://search.cpan.org/~mikem/Device-BCM2835-1.9/lib/Device/BCM2835.pm -/// Matthew Baker has kindly made Python bindings available at: -/// https://github.com/mubeta06/py-libbcm2835 -/// Gary Marks has created a Serial Peripheral Interface (SPI) command-line utility -/// for Raspberry Pi, based on the bcm2835 library. The -/// utility, spincl, is licensed under Open Source GNU GPLv3 by iP Solutions (http://ipsolutionscorp.com), as a -/// free download with source included: http://ipsolutionscorp.com/raspberry-pi-spi-utility/ -/// -/// \par Open Source Licensing GPL V2 -/// -/// This is the appropriate option if you want to share the source code of your -/// application with everyone you distribute it to, and you also want to give them -/// the right to share who uses it. If you wish to use this software under Open -/// Source Licensing, you must contribute all your source code to the open source -/// community in accordance with the GPL Version 2 when your application is -/// distributed. See http://www.gnu.org/copyleft/gpl.html and COPYING -/// -/// \par Acknowledgements -/// -/// Some of this code has been inspired by Dom and Gert. -/// The I2C code has been inspired by Alan Barr. -/// -/// \par Revision History -/// -/// \version 1.0 Initial release -/// \version 1.1 Minor bug fixes -/// \version 1.2 Added support for SPI -/// \version 1.3 Added bcm2835_spi_transfern() -/// \version 1.4 Fixed a problem that prevented SPI CE1 being used. Reported by David Robinson. -/// \version 1.5 Added bcm2835_close() to deinit the library. Suggested by C?sar Ortiz -/// \version 1.6 Document testing on 2012-07-15-wheezy-raspbian and Occidentalisv01 -/// Functions bcm2835_gpio_ren(), bcm2835_gpio_fen(), bcm2835_gpio_hen() -/// bcm2835_gpio_len(), bcm2835_gpio_aren() and bcm2835_gpio_afen() now -/// changes only the pin specified. Other pins that were already previously -/// enabled stay enabled. -/// Added bcm2835_gpio_clr_ren(), bcm2835_gpio_clr_fen(), bcm2835_gpio_clr_hen() -/// bcm2835_gpio_clr_len(), bcm2835_gpio_clr_aren(), bcm2835_gpio_clr_afen() -/// to clear the enable for individual pins, suggested by Andreas Sundstrom. -/// \version 1.7 Added bcm2835_spi_transfernb to support different buffers for read and write. -/// \version 1.8 Improvements to read barrier, as suggested by maddin. -/// \version 1.9 Improvements contributed by mikew: -/// I noticed that it was mallocing memory for the mmaps on /dev/mem. -/// It's not necessary to do that, you can just mmap the file directly, -/// so I've removed the mallocs (and frees). -/// I've also modified delayMicroseconds() to use nanosleep() for long waits, -/// and a busy wait on a high resolution timer for the rest. This is because -/// I've found that calling nanosleep() takes at least 100-200 us. -/// You need to link using '-lrt' using this version. -/// I've added some unsigned casts to the debug prints to silence compiler -/// warnings I was getting, fixed some typos, and changed the value of -/// BCM2835_PAD_HYSTERESIS_ENABLED to 0x08 as per Gert van Loo's doc at -/// http://www.scribd.com/doc/101830961/GPIO-Pads-Control2 -/// Also added a define for the passwrd value that Gert says is needed to -/// change pad control settings. -/// \version 1.10 Changed the names of the delay functions to bcm2835_delay() -/// and bcm2835_delayMicroseconds() to prevent collisions with wiringPi. -/// Macros to map delay()-> bcm2835_delay() and -/// Macros to map delayMicroseconds()-> bcm2835_delayMicroseconds(), which -/// can be disabled by defining BCM2835_NO_DELAY_COMPATIBILITY -/// \version 1.11 Fixed incorrect link to download file -/// \version 1.12 New GPIO pin definitions for RPi version 2 (which has a different GPIO mapping) -/// \version 1.13 New GPIO pin definitions for RPi version 2 plug P5 -/// Hardware base pointers are now available (after initialisation) externally as bcm2835_gpio -/// bcm2835_pwm bcm2835_clk bcm2835_pads bcm2835_spi0. -/// \version 1.14 Now compiles even if CLOCK_MONOTONIC_RAW is not available, uses CLOCK_MONOTONIC instead. -/// Fixed errors in documentation of SPI divider frequencies based on 250MHz clock. -/// Reported by Ben Simpson. -/// \version 1.15 Added bcm2835_close() to end of examples as suggested by Mark Wolfe. -/// \version 1.16 Added bcm2835_gpio_set_multi, bcm2835_gpio_clr_multi and bcm2835_gpio_write_multi -/// to allow a mask of pins to be set all at once. Requested by Sebastian Loncar. -/// \version 1.17 Added bcm2835_gpio_write_mask. Requested by Sebastian Loncar. -/// \version 1.18 Added bcm2835_i2c_* functions. Changes to bcm2835_delayMicroseconds: -/// now uses the RPi system timer counter, instead of clock_gettime, for improved accuracy. -/// No need to link with -lrt now. Contributed by Arjan van Vught. -/// \version 1.19 Removed inlines added by previous patch since they don't seem to work everywhere. -/// Reported by olly. -/// \version 1.20 Patch from Mark Dootson to close /dev/mem after access to the peripherals has been granted. -/// \version 1.21 delayMicroseconds is now not susceptible to 32 bit timer overruns. -/// Patch courtesy Jeremy Mortis. -/// \version 1.22 Fixed incorrect definition of BCM2835_GPFEN0 which broke the ability to set -/// falling edge events. Reported by Mark Dootson. -/// \version 1.23 Added bcm2835_i2c_set_baudrate and bcm2835_i2c_read_register_rs. -/// Improvements to bcm2835_i2c_read and bcm2835_i2c_write functions -/// to fix ocasional reads not completing. Patched by Mark Dootson. -/// \version 1.24 Mark Dootson p[atched a problem with his previously submitted code -/// under high load from other processes. -/// \version 1.25 Updated author and distribution location details to airspayce.com -/// \version 1.26 Added missing unmapmem for pads in bcm2835_close to prevent a memory leak. -/// Reported by Hartmut Henkel. -/// \version 1.27 bcm2835_gpio_set_pad() no longer needs BCM2835_PAD_PASSWRD: it is -/// now automatically included. -/// Added suport for PWM mode with bcm2835_pwm_* functions. -/// \version 1.28 Fixed a problem where bcm2835_spi_writenb() would have problems with transfers of more than -/// 64 bytes dues to read buffer filling. Patched by Peter Würtz. -/// \version 1.29 Further fix to SPI from Peter Würtz. -/// \version 1.30 10 microsecond delays from bcm2835_spi_transfer and bcm2835_spi_transfern for -/// significant performance improvements, Patch by Alan Watson. -/// \version 1.31 Fix a GCC warning about dummy variable, patched by Alan Watson. Thanks. -/// \version 1.32 Added option I2C_V1 definition to compile for version 1 RPi. -/// By default I2C code is generated for the V2 RPi which has SDA1 and SCL1 connected. -/// Contributed by Malcolm Wiles based on work by Arvi Govindaraj. -/// \version 1.33 Added command line utilities i2c and gpio to examples. Contributed by Shahrooz Shahparnia. -/// \version 1.34 Added bcm2835_i2c_write_read_rs() which writes an arbitrary number of bytes, -/// sends a repeat start, and reads from the device. Contributed by Eduardo Steinhorst. -/// \version 1.35 Fix build errors when compiled under Qt. Also performance improvements with SPI transfers. Contributed by Udo Klaas. -/// \version 1.36 Make automake's test runner detect that we're skipping tests when not root, the second -/// one makes us skip the test when using fakeroot (as used when building -/// Debian packages). Contributed by Guido Günther. -/// -/// \author Mike McCauley (mikem@airspayce.com) DO NOT CONTACT THE AUTHOR DIRECTLY: USE THE LISTS - - - -// Defines for BCM2835 +/* bcm2835.h + + C and C++ support for Broadcom BCM 2835 as used in Raspberry Pi + + Author: Mike McCauley + Copyright (C) 2011-2013 Mike McCauley + $Id: bcm2835.h,v 1.20 2015/03/31 04:55:41 mikem Exp mikem $ +*/ + +/*! \mainpage C library for Broadcom BCM 2835 as used in Raspberry Pi + + This is a C library for Raspberry Pi (RPi). It provides access to + GPIO and other IO functions on the Broadcom BCM 2835 chip, + allowing access to the GPIO pins on the + 26 pin IDE plug on the RPi board so you can control and interface with various external devices. + + It provides functions for reading digital inputs and setting digital outputs, using SPI and I2C, + and for accessing the system timers. + Pin event detection is supported by polling (interrupts are not supported). + + It is C++ compatible, and installs as a header file and non-shared library on + any Linux-based distro (but clearly is no use except on Raspberry Pi or another board with + BCM 2835). + + The version of the package that this documentation refers to can be downloaded + from http://www.airspayce.com/mikem/bcm2835/bcm2835-1.50.tar.gz + You can find the latest version at http://www.airspayce.com/mikem/bcm2835 + + Several example programs are provided. + + Based on data in http://elinux.org/RPi_Low-level_peripherals and + http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf + and http://www.scribd.com/doc/101830961/GPIO-Pads-Control2 + + You can also find online help and discussion at http://groups.google.com/group/bcm2835 + Please use that group for all questions and discussions on this topic. + Do not contact the author directly, unless it is to discuss commercial licensing. + Before asking a question or reporting a bug, please read http://www.catb.org/esr/faqs/smart-questions.html + + Tested on debian6-19-04-2012, 2012-07-15-wheezy-raspbian, 2013-07-26-wheezy-raspbian + and Occidentalisv01, 2016-02-09 Raspbian Jessie. + CAUTION: it has been observed that when detect enables such as bcm2835_gpio_len() + are used and the pin is pulled LOW + it can cause temporary hangs on 2012-07-15-wheezy-raspbian, 2013-07-26-wheezy-raspbian + and Occidentalisv01. + Reason for this is not yet determined, but we suspect that an interrupt handler is + hitting a hard loop on those OSs. + If you must use bcm2835_gpio_len() and friends, make sure you disable the pins with + bcm2835_gpio_clr_len() and friends after use. + + \par Running as root + + Prior to the release of Raspbian Jessie in Feb 2016, access to any + peripheral device via /dev/mem on the RPi required the process to + run as root. Raspbian Jessie permits non-root users to access the + GPIO peripheral (only) via /dev/gpiomem, and this library supports + that limited mode of operation. + + If the library runs with effective UID of 0 (ie root), then + bcm2835_init() will attempt to open /dev/mem, and, if successful, it + will permit use of all peripherals and library functions. + + If the library runs with any other effective UID (ie not root), then + bcm2835_init() will attempt to open /dev/gpiomem, and, if + successful, will only permit GPIO operations. In particular, + bcm2835_spi_begin() and bcm2835_i2c_begin() will return false and all + other non-gpio operations may fail silently or crash. + + \par Installation + + This library consists of a single non-shared library and header file, which will be + installed in the usual places by make install + + \code + # download the latest version of the library, say bcm2835-1.xx.tar.gz, then: + tar zxvf bcm2835-1.xx.tar.gz + cd bcm2835-1.xx + ./configure + make + sudo make check + sudo make install + \endcode + + \par Physical Addresses + + The functions bcm2835_peri_read(), bcm2835_peri_write() and bcm2835_peri_set_bits() + are low level peripheral register access functions. They are designed to use + physical addresses as described in section 1.2.3 ARM physical addresses + of the BCM2835 ARM Peripherals manual. + Physical addresses range from 0x20000000 to 0x20FFFFFF for peripherals. The bus + addresses for peripherals are set up to map onto the peripheral bus address range starting at + 0x7E000000. Thus a peripheral advertised in the manual at bus address 0x7Ennnnnn is available at + physical address 0x20nnnnnn. + + On RPI 2, the peripheral addresses are different and the bcm2835 library gets them + from reading /proc/device-tree/soc/ranges. This is only availble with recent versions of the kernel on RPI 2. + + After initialisation, the base address of the various peripheral + registers are available with the following + externals: + bcm2835_gpio + bcm2835_pwm + bcm2835_clk + bcm2835_pads + bcm2835_spio0 + bcm2835_st + bcm2835_bsc0 + bcm2835_bsc1 + + \par Raspberry Pi 2 (RPI2) + + For this library to work correctly on RPI2, you MUST have the device tree support enabled in the kernel. + You should also ensure you are using the latest version of Linux. The library has been tested on RPI2 + with 2015-02-16-raspbian-wheezy and ArchLinuxARM-rpi-2 as of 2015-03-29. + + When device tree suport is enabled, the file /proc/device-tree/soc/ranges will appear in the file system, + and the bcm2835 module relies on its presence to correctly run on RPI2 (it is optional for RPI1). + Without device tree support enabled and the presence of this file, it will not work on RPI2. + + To enable device tree support: + + \code + sudo raspi-config + under Advanced Options - enable Device Tree + Reboot. + \endcode + + \par Pin Numbering + + The GPIO pin numbering as used by RPi is different to and inconsistent with the underlying + BCM 2835 chip pin numbering. http://elinux.org/RPi_BCM2835_GPIOs + + RPi has a 26 pin IDE header that provides access to some of the GPIO pins on the BCM 2835, + as well as power and ground pins. Not all GPIO pins on the BCM 2835 are available on the + IDE header. + + RPi Version 2 also has a P5 connector with 4 GPIO pins, 5V, 3.3V and Gnd. + + The functions in this library are designed to be passed the BCM 2835 GPIO pin number and _not_ + the RPi pin number. There are symbolic definitions for each of the available pins + that you should use for convenience. See \ref RPiGPIOPin. + + \par SPI Pins + + The bcm2835_spi_* functions allow you to control the BCM 2835 SPI0 interface, + allowing you to send and received data by SPI (Serial Peripheral Interface). + For more information about SPI, see http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus + + When bcm2835_spi_begin() is called it changes the bahaviour of the SPI interface pins from their + default GPIO behaviour in order to support SPI. While SPI is in use, you will not be able + to control the state of the SPI pins through the usual bcm2835_spi_gpio_write(). + When bcm2835_spi_end() is called, the SPI pins will all revert to inputs, and can then be + configured and controled with the usual bcm2835_gpio_* calls. + + The Raspberry Pi GPIO pins used for SPI are: + + - P1-19 (MOSI) + - P1-21 (MISO) + - P1-23 (CLK) + - P1-24 (CE0) + - P1-26 (CE1) + + \par I2C Pins + + The bcm2835_i2c_* functions allow you to control the BCM 2835 BSC interface, + allowing you to send and received data by I2C ("eye-squared cee"; generically referred to as "two-wire interface") . + For more information about I?C, see http://en.wikipedia.org/wiki/I%C2%B2C + + The Raspberry Pi V2 GPIO pins used for I2C are: + + - P1-03 (SDA) + - P1-05 (SLC) + + \par PWM + + The BCM2835 supports hardware PWM on a limited subset of GPIO pins. This bcm2835 library provides + functions for configuring and controlling PWM output on these pins. + + The BCM2835 contains 2 independent PWM channels (0 and 1), each of which be connnected to a limited subset of + GPIO pins. The following GPIO pins may be connected to the following PWM channels (from section 9.5): + \code + GPIO PIN RPi pin PWM Channel ALT FUN + 12 0 0 + 13 1 0 + 18 1-12 0 5 + 19 1 5 + 40 0 0 + 41 1 0 + 45 1 0 + 52 0 1 + 53 1 1 + \endcode + In order for a GPIO pin to emit output from its PWM channel, it must be set to the Alt Function given above. + Note carefully that current versions of the Raspberry Pi only expose one of these pins (GPIO 18 = RPi Pin 1-12) + on the IO headers, and therefore this is the only IO pin on the RPi that can be used for PWM. + Further it must be set to ALT FUN 5 to get PWM output. + + Both PWM channels are driven by the same PWM clock, whose clock dvider can be varied using + bcm2835_pwm_set_clock(). Each channel can be separately enabled with bcm2835_pwm_set_mode(). + The average output of the PWM channel is determined by the ratio of DATA/RANGE for that channel. + Use bcm2835_pwm_set_range() to set the range and bcm2835_pwm_set_data() to set the data in that ratio + + Each PWM channel can run in either Balanced or Mark-Space mode. In Balanced mode, the hardware + sends a combination of clock pulses that results in an overall DATA pulses per RANGE pulses. + In Mark-Space mode, the hardware sets the output HIGH for DATA clock pulses wide, followed by + LOW for RANGE-DATA clock pulses. + + The PWM clock can be set to control the PWM pulse widths. The PWM clock is derived from + a 19.2MHz clock. You can set any divider, but some common ones are provided by the BCM2835_PWM_CLOCK_DIVIDER_* + values of \ref bcm2835PWMClockDivider. + + For example, say you wanted to drive a DC motor with PWM at about 1kHz, + and control the speed in 1/1024 increments from + 0/1024 (stopped) through to 1024/1024 (full on). In that case you might set the + clock divider to be 16, and the RANGE to 1024. The pulse repetition frequency will be + 1.2MHz/1024 = 1171.875Hz. + + \par SPI + + In order for bcm2835 library SPI to work, you may need to disable the SPI kernel module using: + + \code + sudo raspi-config + under Advanced Options - enable Device Tree + under Advanced Options - disable SPI + Reboot. + \endcode + + \par Real Time performance constraints + + The bcm2835 is a library for user programs (i.e. they run in 'userland'). + Such programs are not part of the kernel and are usually + subject to paging and swapping by the kernel while it does other things besides running your program. + This means that you should not expect to get real-time performance or + real-time timing constraints from such programs. In particular, there is no guarantee that the + bcm2835_delay() and bcm2835_delayMicroseconds() will return after exactly the time requested. + In fact, depending on other activity on the host, IO etc, you might get significantly longer delay times + than the one you asked for. So please dont expect to get exactly the time delay you request. + + Arjan reports that you can prevent swapping on Linux with the following code fragment: + + \code + struct sched_param sp; + memset(&sp, 0, sizeof(sp)); + sp.sched_priority = sched_get_priority_max(SCHED_FIFO); + sched_setscheduler(0, SCHED_FIFO, &sp); + mlockall(MCL_CURRENT | MCL_FUTURE); + \endcode + + \par Bindings to other languages + + mikem has made Perl bindings available at CPAN: + http://search.cpan.org/~mikem/Device-BCM2835-1.9/lib/Device/BCM2835.pm + Matthew Baker has kindly made Python bindings available at: + https: github.com/mubeta06/py-libbcm2835 + Gary Marks has created a Serial Peripheral Interface (SPI) command-line utility + for Raspberry Pi, based on the bcm2835 library. The + utility, spincl, is licensed under Open Source GNU GPLv3 by iP Solutions (http://ipsolutionscorp.com), as a + free download with source included: http://ipsolutionscorp.com/raspberry-pi-spi-utility/ + + \par Open Source Licensing GPL V2 + + This is the appropriate option if you want to share the source code of your + application with everyone you distribute it to, and you also want to give them + the right to share who uses it. If you wish to use this software under Open + Source Licensing, you must contribute all your source code to the open source + community in accordance with the GPL Version 2 when your application is + distributed. See http://www.gnu.org/copyleft/gpl.html and COPYING + + \par Acknowledgements + + Some of this code has been inspired by Dom and Gert. + The I2C code has been inspired by Alan Barr. + + \par Revision History + + \version 1.0 Initial release + + \version 1.1 Minor bug fixes + + \version 1.2 Added support for SPI + + \version 1.3 Added bcm2835_spi_transfern() + + \version 1.4 Fixed a problem that prevented SPI CE1 being used. Reported by David Robinson. + + \version 1.5 Added bcm2835_close() to deinit the library. Suggested by C?sar Ortiz + + \version 1.6 Document testing on 2012-07-15-wheezy-raspbian and Occidentalisv01 + Functions bcm2835_gpio_ren(), bcm2835_gpio_fen(), bcm2835_gpio_hen() + bcm2835_gpio_len(), bcm2835_gpio_aren() and bcm2835_gpio_afen() now + changes only the pin specified. Other pins that were already previously + enabled stay enabled. + Added bcm2835_gpio_clr_ren(), bcm2835_gpio_clr_fen(), bcm2835_gpio_clr_hen() + bcm2835_gpio_clr_len(), bcm2835_gpio_clr_aren(), bcm2835_gpio_clr_afen() + to clear the enable for individual pins, suggested by Andreas Sundstrom. + + \version 1.7 Added bcm2835_spi_transfernb to support different buffers for read and write. + + \version 1.8 Improvements to read barrier, as suggested by maddin. + + \version 1.9 Improvements contributed by mikew: + I noticed that it was mallocing memory for the mmaps on /dev/mem. + It's not necessary to do that, you can just mmap the file directly, + so I've removed the mallocs (and frees). + I've also modified delayMicroseconds() to use nanosleep() for long waits, + and a busy wait on a high resolution timer for the rest. This is because + I've found that calling nanosleep() takes at least 100-200 us. + You need to link using '-lrt' using this version. + I've added some unsigned casts to the debug prints to silence compiler + warnings I was getting, fixed some typos, and changed the value of + BCM2835_PAD_HYSTERESIS_ENABLED to 0x08 as per Gert van Loo's doc at + http://www.scribd.com/doc/101830961/GPIO-Pads-Control2 + Also added a define for the passwrd value that Gert says is needed to + change pad control settings. + + \version 1.10 Changed the names of the delay functions to bcm2835_delay() + and bcm2835_delayMicroseconds() to prevent collisions with wiringPi. + Macros to map delay()-> bcm2835_delay() and + Macros to map delayMicroseconds()-> bcm2835_delayMicroseconds(), which + can be disabled by defining BCM2835_NO_DELAY_COMPATIBILITY + + \version 1.11 Fixed incorrect link to download file + + \version 1.12 New GPIO pin definitions for RPi version 2 (which has a different GPIO mapping) + + \version 1.13 New GPIO pin definitions for RPi version 2 plug P5 + Hardware base pointers are now available (after initialisation) externally as bcm2835_gpio + bcm2835_pwm bcm2835_clk bcm2835_pads bcm2835_spi0. + + \version 1.14 Now compiles even if CLOCK_MONOTONIC_RAW is not available, uses CLOCK_MONOTONIC instead. + Fixed errors in documentation of SPI divider frequencies based on 250MHz clock. + Reported by Ben Simpson. + + \version 1.15 Added bcm2835_close() to end of examples as suggested by Mark Wolfe. + + \version 1.16 Added bcm2835_gpio_set_multi, bcm2835_gpio_clr_multi and bcm2835_gpio_write_multi + to allow a mask of pins to be set all at once. Requested by Sebastian Loncar. + + \version 1.17 Added bcm2835_gpio_write_mask. Requested by Sebastian Loncar. + + \version 1.18 Added bcm2835_i2c_* functions. Changes to bcm2835_delayMicroseconds: + now uses the RPi system timer counter, instead of clock_gettime, for improved accuracy. + No need to link with -lrt now. Contributed by Arjan van Vught. + \version 1.19 Removed inlines added by previous patch since they don't seem to work everywhere. + Reported by olly. + + \version 1.20 Patch from Mark Dootson to close /dev/mem after access to the peripherals has been granted. + + \version 1.21 delayMicroseconds is now not susceptible to 32 bit timer overruns. + Patch courtesy Jeremy Mortis. + + \version 1.22 Fixed incorrect definition of BCM2835_GPFEN0 which broke the ability to set + falling edge events. Reported by Mark Dootson. + + \version 1.23 Added bcm2835_i2c_set_baudrate and bcm2835_i2c_read_register_rs. + Improvements to bcm2835_i2c_read and bcm2835_i2c_write functions + to fix ocasional reads not completing. Patched by Mark Dootson. + + \version 1.24 Mark Dootson p[atched a problem with his previously submitted code + under high load from other processes. + + \version 1.25 Updated author and distribution location details to airspayce.com + + \version 1.26 Added missing unmapmem for pads in bcm2835_close to prevent a memory leak. + Reported by Hartmut Henkel. + + \version 1.27 bcm2835_gpio_set_pad() no longer needs BCM2835_PAD_PASSWRD: it is + now automatically included. + Added suport for PWM mode with bcm2835_pwm_* functions. + + \version 1.28 Fixed a problem where bcm2835_spi_writenb() would have problems with transfers of more than + 64 bytes dues to read buffer filling. Patched by Peter Würtz. + + \version 1.29 Further fix to SPI from Peter Würtz. + + \version 1.30 10 microsecond delays from bcm2835_spi_transfer and bcm2835_spi_transfern for + significant performance improvements, Patch by Alan Watson. + + \version 1.31 Fix a GCC warning about dummy variable, patched by Alan Watson. Thanks. + + \version 1.32 Added option I2C_V1 definition to compile for version 1 RPi. + By default I2C code is generated for the V2 RPi which has SDA1 and SCL1 connected. + Contributed by Malcolm Wiles based on work by Arvi Govindaraj. + + \version 1.33 Added command line utilities i2c and gpio to examples. Contributed by Shahrooz Shahparnia. + + \version 1.34 Added bcm2835_i2c_write_read_rs() which writes an arbitrary number of bytes, + sends a repeat start, and reads from the device. Contributed by Eduardo Steinhorst. + + \version 1.35 Fix build errors when compiled under Qt. Also performance improvements with SPI transfers. Contributed b Udo Klaas. + + \version 1.36 Make automake's test runner detect that we're skipping tests when not root, the second + one makes us skip the test when using fakeroot (as used when building + Debian packages). Contributed by Guido Günther. + + \version 1.37 Moved confiure.in to configure.ac as receommnded by autoreconf.
+ Improvements to bcm2835_st_read to account for possible timer overflow, contributed by 'Ed'.
+ Added definitions for Raspberry Pi B+ J8 header GPIO pins.
+ + \version 1.38 Added bcm2835_regbase for the benefit of C# wrappers, patch by Frank Hommers
+ + \version 1.39 Beta version of RPi2 compatibility. Not tested here on RPi2 hardware. + Testers please confirm correct operation on RPi2.
+ Unneccessary 'volatile' qualifiers removed from all variables and signatures.
+ Removed unsupportable PWM dividers, based on a report from Christophe Cecillon.
+ Minor improvements to spi.c example.
+ + \version 1.40 Correct operation on RPi2 has been confirmed.
+ Fixed a number of compiler errors and warnings that occur when bcm2835.h is included + in code compiled with -Wall -Woverflow -Wstrict-overflow -Wshadow -Wextra -pedantic. + Reported by tlhackque.
+ Fixed a problem where calling bcm2835_delayMicroseconds loops forever when debug is set. Reported by tlhackque.
+ Reinstated use of volatile in 2 functions where there was a danger of lost reads or writes. Reported by tlhackque.
+ + \version 1.41 Added BCM2835_VERSION macro and new function bcm2835_version(); Requested by tlhackque.
+ Improvements to peripheral memory barriers as suggested by tlhackque.
+ Reinstated some necessary volatile declarations as requested by tlhackque.
+ + \version 1.42 Further improvements to memory barriers with the patient assistance and patches of tlhackque.
+ + \version 1.43 Fixed problems with compiling barriers on RPI 2 with Arch Linux and gcc 4.9.2. + Reported and patched by Lars Christensen.
+ Testing on RPI 2, with ArchLinuxARM-rpi-2-latest and 2015-02-16-raspbian-wheezy.
+ + \version 1.44 Added documention about the need for device tree to be enabled on RPI2.
+ Improvements to detection of availablity of DMB instruction based on value of __ARM_ARCH macro.
+ + \version 1.45 Fixed an error in the pad group offsets that would prevent bcm2835_gpio_set_pad() + and bcm2835_gpio_pad() working correctly with non-0 pad groups. Reported by Guido. + + \version 1.46 2015-09-18 + Added symbolic definitions for remaining pins on 40 pin GPIO header on RPi 2.
+ + \version 1.47 2015-11-18 + Fixed possibly incorrect reads in bcm2835_i2c_read_register_rs, patch from Eckhardt Ulrich.
+ + \version 1.48 2015-12-08 + Added patch from Eckhardt Ulrich that fixed problems that could cause hanging with bcm2835_i2c_read_register_rs + and others. + + \version 1.49 2016-01-05 + Added patch from Jonathan Perkin with new functions bcm2835_gpio_eds_multi() and bcm2835_gpio_set_eds_multi(). + + \version 1.50 2016-02-28 + Added support for running as non-root, permitting access to GPIO only. Functions + bcm2835_spi_begin() and bcm2835_i2c_begin() will now return 0 if not running as root + (which prevents access to the SPI and I2C peripherals, amongst others). + Testing on Raspbian Jessie. + + \author Mike McCauley (mikem@airspayce.com) DO NOT CONTACT THE AUTHOR DIRECTLY: USE THE LISTS +*/ + + +/* Defines for BCM2835 */ #ifndef BCM2835_H #define BCM2835_H #include -/// \defgroup constants Constants for passing to and from library functions -/// The values here are designed to be passed to various functions in the bcm2835 library. -/// @{ +#define BCM2835_VERSION 10050 /* Version 1.50 */ + +/* RPi 2 is ARM v7, and has DMB instruction for memory barriers. + Older RPis are ARM v6 and don't, so a coprocessor instruction must be used instead. + However, not all versions of gcc in all distros support the dmb assembler instruction even on conmpatible processors. + This test is so any ARMv7 or higher processors with suitable GCC will use DMB. +*/ +#if __ARM_ARCH >= 7 +#define BCM2835_HAVE_DMB +#endif +/*! \defgroup constants Constants for passing to and from library functions + The values here are designed to be passed to various functions in the bcm2835 library. + @{ +*/ -/// This means pin HIGH, true, 3.3volts on a pin. +/*! This means pin HIGH, true, 3.3volts on a pin. */ #define HIGH 0x1 -/// This means pin LOW, false, 0volts on a pin. +/*! This means pin LOW, false, 0volts on a pin. */ #define LOW 0x0 -/// Speed of the core clock core_clk -#define BCM2835_CORE_CLK_HZ 250000000 ///< 250 MHz - -// Physical addresses for various peripheral register sets -/// Base Physical Address of the BCM 2835 peripheral registers +/*! Speed of the core clock core_clk */ +#define BCM2835_CORE_CLK_HZ 250000000 /*!< 250 MHz */ + +/*! On RPi2 with BCM2836, and all recent OSs, the base of the peripherals is read from a /proc file */ +#define BMC2835_RPI2_DT_FILENAME "/proc/device-tree/soc/ranges" +/*! Offset into BMC2835_RPI2_DT_FILENAME for the peripherals base address */ +#define BMC2835_RPI2_DT_PERI_BASE_ADDRESS_OFFSET 4 +/*! 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 is derived from /proc/device-tree/soc/ranges + If /proc/device-tree/soc/ranges exists on a RPi 1 OS, it would be expected to contain the + following numbers: +*/ +/*! Peripherals block base address on RPi 1 */ #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) - - -/// Base of the ST (System Timer) registers. -/// Available after bcm2835_init has been called +/*! Size of the peripherals 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 uint32_t *bcm2835_peripherals; + +/*! Base of the ST (System Timer) registers. + Available after bcm2835_init has been called (as root) +*/ extern volatile uint32_t *bcm2835_st; -/// Base of the GPIO registers. -/// Available after bcm2835_init has been called +/*! Base of the GPIO registers. + Available after bcm2835_init has been called +*/ extern volatile uint32_t *bcm2835_gpio; -/// Base of the PWM registers. -/// Available after bcm2835_init has been called +/*! Base of the PWM registers. + Available after bcm2835_init has been called (as root) +*/ extern volatile uint32_t *bcm2835_pwm; -/// Base of the CLK registers. -/// Available after bcm2835_init has been called +/*! Base of the CLK registers. + Available after bcm2835_init has been called (as root) +*/ extern volatile uint32_t *bcm2835_clk; -/// Base of the PADS registers. -/// Available after bcm2835_init has been called +/*! Base of the PADS registers. + Available after bcm2835_init has been called (as root) +*/ extern volatile uint32_t *bcm2835_pads; -/// Base of the SPI0 registers. -/// Available after bcm2835_init has been called +/*! Base of the SPI0 registers. + Available after bcm2835_init has been called (as root) +*/ extern volatile uint32_t *bcm2835_spi0; -/// Base of the BSC0 registers. -/// Available after bcm2835_init has been called +/*! Base of the BSC0 registers. + Available after bcm2835_init has been called (as root) +*/ extern volatile uint32_t *bcm2835_bsc0; -/// Base of the BSC1 registers. -/// Available after bcm2835_init has been called +/*! Base of the BSC1 registers. + Available after bcm2835_init has been called (as root) +*/ extern volatile uint32_t *bcm2835_bsc1; -/// Size of memory page on RPi +/*! \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) -/// Size of memory block on RPi +/*! Size of memory block on RPi */ #define BCM2835_BLOCK_SIZE (4*1024) -// Defines for GPIO -// The BCM2835 has 54 GPIO pins. -// BCM2835 data sheet, Page 90 onwards. -/// GPIO register offsets from BCM2835_GPIO_BASE. Offsets into the GPIO Peripheral block in bytes per 6.1 Register View -#define BCM2835_GPFSEL0 0x0000 ///< GPIO Function Select 0 -#define BCM2835_GPFSEL1 0x0004 ///< GPIO Function Select 1 -#define BCM2835_GPFSEL2 0x0008 ///< GPIO Function Select 2 -#define BCM2835_GPFSEL3 0x000c ///< GPIO Function Select 3 -#define BCM2835_GPFSEL4 0x0010 ///< GPIO Function Select 4 -#define BCM2835_GPFSEL5 0x0014 ///< GPIO Function Select 5 -#define BCM2835_GPSET0 0x001c ///< GPIO Pin Output Set 0 -#define BCM2835_GPSET1 0x0020 ///< GPIO Pin Output Set 1 -#define BCM2835_GPCLR0 0x0028 ///< GPIO Pin Output Clear 0 -#define BCM2835_GPCLR1 0x002c ///< GPIO Pin Output Clear 1 -#define BCM2835_GPLEV0 0x0034 ///< GPIO Pin Level 0 -#define BCM2835_GPLEV1 0x0038 ///< GPIO Pin Level 1 -#define BCM2835_GPEDS0 0x0040 ///< GPIO Pin Event Detect Status 0 -#define BCM2835_GPEDS1 0x0044 ///< GPIO Pin Event Detect Status 1 -#define BCM2835_GPREN0 0x004c ///< GPIO Pin Rising Edge Detect Enable 0 -#define BCM2835_GPREN1 0x0050 ///< GPIO Pin Rising Edge Detect Enable 1 -#define BCM2835_GPFEN0 0x0058 ///< GPIO Pin Falling Edge Detect Enable 0 -#define BCM2835_GPFEN1 0x005c ///< GPIO Pin Falling Edge Detect Enable 1 -#define BCM2835_GPHEN0 0x0064 ///< GPIO Pin High Detect Enable 0 -#define BCM2835_GPHEN1 0x0068 ///< GPIO Pin High Detect Enable 1 -#define BCM2835_GPLEN0 0x0070 ///< GPIO Pin Low Detect Enable 0 -#define BCM2835_GPLEN1 0x0074 ///< GPIO Pin Low Detect Enable 1 -#define BCM2835_GPAREN0 0x007c ///< GPIO Pin Async. Rising Edge Detect 0 -#define BCM2835_GPAREN1 0x0080 ///< GPIO Pin Async. Rising Edge Detect 1 -#define BCM2835_GPAFEN0 0x0088 ///< GPIO Pin Async. Falling Edge Detect 0 -#define BCM2835_GPAFEN1 0x008c ///< GPIO Pin Async. Falling Edge Detect 1 -#define BCM2835_GPPUD 0x0094 ///< GPIO Pin Pull-up/down Enable -#define BCM2835_GPPUDCLK0 0x0098 ///< GPIO Pin Pull-up/down Enable Clock 0 -#define BCM2835_GPPUDCLK1 0x009c ///< GPIO Pin Pull-up/down Enable Clock 1 - -/// \brief bcm2835PortFunction -/// Port function select modes for bcm2835_gpio_fsel() +/* Defines for GPIO + The BCM2835 has 54 GPIO pins. + BCM2835 data sheet, Page 90 onwards. +*/ +/*! GPIO register offsets from BCM2835_GPIO_BASE. + Offsets into the GPIO Peripheral block in bytes per 6.1 Register View +*/ +#define BCM2835_GPFSEL0 0x0000 /*!< GPIO Function Select 0 */ +#define BCM2835_GPFSEL1 0x0004 /*!< GPIO Function Select 1 */ +#define BCM2835_GPFSEL2 0x0008 /*!< GPIO Function Select 2 */ +#define BCM2835_GPFSEL3 0x000c /*!< GPIO Function Select 3 */ +#define BCM2835_GPFSEL4 0x0010 /*!< GPIO Function Select 4 */ +#define BCM2835_GPFSEL5 0x0014 /*!< GPIO Function Select 5 */ +#define BCM2835_GPSET0 0x001c /*!< GPIO Pin Output Set 0 */ +#define BCM2835_GPSET1 0x0020 /*!< GPIO Pin Output Set 1 */ +#define BCM2835_GPCLR0 0x0028 /*!< GPIO Pin Output Clear 0 */ +#define BCM2835_GPCLR1 0x002c /*!< GPIO Pin Output Clear 1 */ +#define BCM2835_GPLEV0 0x0034 /*!< GPIO Pin Level 0 */ +#define BCM2835_GPLEV1 0x0038 /*!< GPIO Pin Level 1 */ +#define BCM2835_GPEDS0 0x0040 /*!< GPIO Pin Event Detect Status 0 */ +#define BCM2835_GPEDS1 0x0044 /*!< GPIO Pin Event Detect Status 1 */ +#define BCM2835_GPREN0 0x004c /*!< GPIO Pin Rising Edge Detect Enable 0 */ +#define BCM2835_GPREN1 0x0050 /*!< GPIO Pin Rising Edge Detect Enable 1 */ +#define BCM2835_GPFEN0 0x0058 /*!< GPIO Pin Falling Edge Detect Enable 0 */ +#define BCM2835_GPFEN1 0x005c /*!< GPIO Pin Falling Edge Detect Enable 1 */ +#define BCM2835_GPHEN0 0x0064 /*!< GPIO Pin High Detect Enable 0 */ +#define BCM2835_GPHEN1 0x0068 /*!< GPIO Pin High Detect Enable 1 */ +#define BCM2835_GPLEN0 0x0070 /*!< GPIO Pin Low Detect Enable 0 */ +#define BCM2835_GPLEN1 0x0074 /*!< GPIO Pin Low Detect Enable 1 */ +#define BCM2835_GPAREN0 0x007c /*!< GPIO Pin Async. Rising Edge Detect 0 */ +#define BCM2835_GPAREN1 0x0080 /*!< GPIO Pin Async. Rising Edge Detect 1 */ +#define BCM2835_GPAFEN0 0x0088 /*!< GPIO Pin Async. Falling Edge Detect 0 */ +#define BCM2835_GPAFEN1 0x008c /*!< GPIO Pin Async. Falling Edge Detect 1 */ +#define BCM2835_GPPUD 0x0094 /*!< GPIO Pin Pull-up/down Enable */ +#define BCM2835_GPPUDCLK0 0x0098 /*!< GPIO Pin Pull-up/down Enable Clock 0 */ +#define BCM2835_GPPUDCLK1 0x009c /*!< GPIO Pin Pull-up/down Enable Clock 1 */ + +/*! \brief bcm2835PortFunction + Port function select modes for bcm2835_gpio_fsel() +*/ typedef enum { - BCM2835_GPIO_FSEL_INPT = 0b000, ///< Input - BCM2835_GPIO_FSEL_OUTP = 0b001, ///< Output - BCM2835_GPIO_FSEL_ALT0 = 0b100, ///< Alternate function 0 - BCM2835_GPIO_FSEL_ALT1 = 0b101, ///< Alternate function 1 - BCM2835_GPIO_FSEL_ALT2 = 0b110, ///< Alternate function 2 - BCM2835_GPIO_FSEL_ALT3 = 0b111, ///< Alternate function 3 - BCM2835_GPIO_FSEL_ALT4 = 0b011, ///< Alternate function 4 - BCM2835_GPIO_FSEL_ALT5 = 0b010, ///< Alternate function 5 - BCM2835_GPIO_FSEL_MASK = 0b111 ///< Function select bits mask + BCM2835_GPIO_FSEL_INPT = 0x00, /*!< Input 0b000 */ + BCM2835_GPIO_FSEL_OUTP = 0x01, /*!< Output 0b001 */ + BCM2835_GPIO_FSEL_ALT0 = 0x04, /*!< Alternate function 0 0b100 */ + BCM2835_GPIO_FSEL_ALT1 = 0x05, /*!< Alternate function 1 0b101 */ + BCM2835_GPIO_FSEL_ALT2 = 0x06, /*!< Alternate function 2 0b110, */ + BCM2835_GPIO_FSEL_ALT3 = 0x07, /*!< Alternate function 3 0b111 */ + BCM2835_GPIO_FSEL_ALT4 = 0x03, /*!< Alternate function 4 0b011 */ + BCM2835_GPIO_FSEL_ALT5 = 0x02, /*!< Alternate function 5 0b010 */ + BCM2835_GPIO_FSEL_MASK = 0x07 /*!< Function select bits mask 0b111 */ } bcm2835FunctionSelect; -/// \brief bcm2835PUDControl -/// Pullup/Pulldown defines for bcm2835_gpio_pud() +/*! \brief bcm2835PUDControl + Pullup/Pulldown defines for bcm2835_gpio_pud() +*/ typedef enum { - BCM2835_GPIO_PUD_OFF = 0b00, ///< Off ? disable pull-up/down - BCM2835_GPIO_PUD_DOWN = 0b01, ///< Enable Pull Down control - BCM2835_GPIO_PUD_UP = 0b10 ///< Enable Pull Up control + BCM2835_GPIO_PUD_OFF = 0x00, /*!< Off ? disable pull-up/down 0b00 */ + BCM2835_GPIO_PUD_DOWN = 0x01, /*!< Enable Pull Down control 0b01 */ + BCM2835_GPIO_PUD_UP = 0x02 /*!< Enable Pull Up control 0b10 */ } bcm2835PUDControl; -/// Pad control register offsets from BCM2835_GPIO_PADS -#define BCM2835_PADS_GPIO_0_27 0x002c ///< Pad control register for pads 0 to 27 -#define BCM2835_PADS_GPIO_28_45 0x0030 ///< Pad control register for pads 28 to 45 -#define BCM2835_PADS_GPIO_46_53 0x0034 ///< Pad control register for pads 46 to 53 - -/// Pad Control masks -#define BCM2835_PAD_PASSWRD (0x5A << 24) ///< Password to enable setting pad mask -#define BCM2835_PAD_SLEW_RATE_UNLIMITED 0x10 ///< Slew rate unlimited -#define BCM2835_PAD_HYSTERESIS_ENABLED 0x08 ///< Hysteresis enabled -#define BCM2835_PAD_DRIVE_2mA 0x00 ///< 2mA drive current -#define BCM2835_PAD_DRIVE_4mA 0x01 ///< 4mA drive current -#define BCM2835_PAD_DRIVE_6mA 0x02 ///< 6mA drive current -#define BCM2835_PAD_DRIVE_8mA 0x03 ///< 8mA drive current -#define BCM2835_PAD_DRIVE_10mA 0x04 ///< 10mA drive current -#define BCM2835_PAD_DRIVE_12mA 0x05 ///< 12mA drive current -#define BCM2835_PAD_DRIVE_14mA 0x06 ///< 14mA drive current -#define BCM2835_PAD_DRIVE_16mA 0x07 ///< 16mA drive current - -/// \brief bcm2835PadGroup -/// Pad group specification for bcm2835_gpio_pad() +/*! Pad control register offsets from BCM2835_GPIO_PADS */ +#define BCM2835_PADS_GPIO_0_27 0x002c /*!< Pad control register for pads 0 to 27 */ +#define BCM2835_PADS_GPIO_28_45 0x0030 /*!< Pad control register for pads 28 to 45 */ +#define BCM2835_PADS_GPIO_46_53 0x0034 /*!< Pad control register for pads 46 to 53 */ + +/*! Pad Control masks */ +#define BCM2835_PAD_PASSWRD (0x5A << 24) /*!< Password to enable setting pad mask */ +#define BCM2835_PAD_SLEW_RATE_UNLIMITED 0x10 /*!< Slew rate unlimited */ +#define BCM2835_PAD_HYSTERESIS_ENABLED 0x08 /*!< Hysteresis enabled */ +#define BCM2835_PAD_DRIVE_2mA 0x00 /*!< 2mA drive current */ +#define BCM2835_PAD_DRIVE_4mA 0x01 /*!< 4mA drive current */ +#define BCM2835_PAD_DRIVE_6mA 0x02 /*!< 6mA drive current */ +#define BCM2835_PAD_DRIVE_8mA 0x03 /*!< 8mA drive current */ +#define BCM2835_PAD_DRIVE_10mA 0x04 /*!< 10mA drive current */ +#define BCM2835_PAD_DRIVE_12mA 0x05 /*!< 12mA drive current */ +#define BCM2835_PAD_DRIVE_14mA 0x06 /*!< 14mA drive current */ +#define BCM2835_PAD_DRIVE_16mA 0x07 /*!< 16mA drive current */ + +/*! \brief bcm2835PadGroup + Pad group specification for bcm2835_gpio_pad() +*/ typedef enum { - BCM2835_PAD_GROUP_GPIO_0_27 = 0, ///< Pad group for GPIO pads 0 to 27 - BCM2835_PAD_GROUP_GPIO_28_45 = 1, ///< Pad group for GPIO pads 28 to 45 - BCM2835_PAD_GROUP_GPIO_46_53 = 2 ///< Pad group for GPIO pads 46 to 53 + BCM2835_PAD_GROUP_GPIO_0_27 = 0, /*!< Pad group for GPIO pads 0 to 27 */ + BCM2835_PAD_GROUP_GPIO_28_45 = 1, /*!< Pad group for GPIO pads 28 to 45 */ + BCM2835_PAD_GROUP_GPIO_46_53 = 2 /*!< Pad group for GPIO pads 46 to 53 */ } bcm2835PadGroup; -/// \brief GPIO Pin Numbers -/// -/// Here we define Raspberry Pin GPIO pins on P1 in terms of the underlying BCM GPIO pin numbers. -/// These can be passed as a pin number to any function requiring a pin. -/// Not all pins on the RPi 26 bin IDE plug are connected to GPIO pins -/// and some can adopt an alternate function. -/// RPi version 2 has some slightly different pinouts, and these are values RPI_V2_*. -/// 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()), pins 19, 21, 23, 24, 26 are dedicated to SPI -/// and cant be controlled independently +/*! \brief GPIO Pin Numbers + + Here we define Raspberry Pin GPIO pins on P1 in terms of the underlying BCM GPIO pin numbers. + These can be passed as a pin number to any function requiring a pin. + Not all pins on the RPi 26 bin IDE plug are connected to GPIO pins + and some can adopt an alternate function. + RPi version 2 has some slightly different pinouts, and these are values RPI_V2_*. + 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. + 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 - RPI_GPIO_P1_05 = 1, ///< Version 1, Pin P1-05 - RPI_GPIO_P1_07 = 4, ///< Version 1, Pin P1-07 - RPI_GPIO_P1_08 = 14, ///< Version 1, Pin P1-08, defaults to alt function 0 UART0_TXD - RPI_GPIO_P1_10 = 15, ///< Version 1, Pin P1-10, defaults to alt function 0 UART0_RXD - RPI_GPIO_P1_11 = 17, ///< Version 1, Pin P1-11 - RPI_GPIO_P1_12 = 18, ///< Version 1, Pin P1-12, can be PWM channel 0 in ALT FUN 5 - RPI_GPIO_P1_13 = 21, ///< Version 1, Pin P1-13 - RPI_GPIO_P1_15 = 22, ///< Version 1, Pin P1-15 - RPI_GPIO_P1_16 = 23, ///< Version 1, Pin P1-16 - RPI_GPIO_P1_18 = 24, ///< Version 1, Pin P1-18 - RPI_GPIO_P1_19 = 10, ///< Version 1, Pin P1-19, MOSI when SPI0 in use - RPI_GPIO_P1_21 = 9, ///< Version 1, Pin P1-21, MISO when SPI0 in use - RPI_GPIO_P1_22 = 25, ///< Version 1, Pin P1-22 - RPI_GPIO_P1_23 = 11, ///< Version 1, Pin P1-23, CLK when SPI0 in use - RPI_GPIO_P1_24 = 8, ///< Version 1, Pin P1-24, CE0 when SPI0 in use - RPI_GPIO_P1_26 = 7, ///< Version 1, Pin P1-26, CE1 when SPI0 in use - - // RPi Version 2 - RPI_V2_GPIO_P1_03 = 2, ///< Version 2, Pin P1-03 - RPI_V2_GPIO_P1_05 = 3, ///< Version 2, Pin P1-05 - RPI_V2_GPIO_P1_07 = 4, ///< Version 2, Pin P1-07 - RPI_V2_GPIO_P1_08 = 14, ///< Version 2, Pin P1-08, defaults to alt function 0 UART0_TXD - RPI_V2_GPIO_P1_10 = 15, ///< Version 2, Pin P1-10, defaults to alt function 0 UART0_RXD - RPI_V2_GPIO_P1_11 = 17, ///< Version 2, Pin P1-11 - RPI_V2_GPIO_P1_12 = 18, ///< Version 2, Pin P1-12, can be PWM channel 0 in ALT FUN 5 - RPI_V2_GPIO_P1_13 = 27, ///< Version 2, Pin P1-13 - RPI_V2_GPIO_P1_15 = 22, ///< Version 2, Pin P1-15 - RPI_V2_GPIO_P1_16 = 23, ///< Version 2, Pin P1-16 - RPI_V2_GPIO_P1_18 = 24, ///< Version 2, Pin P1-18 - RPI_V2_GPIO_P1_19 = 10, ///< Version 2, Pin P1-19, MOSI when SPI0 in use - RPI_V2_GPIO_P1_21 = 9, ///< Version 2, Pin P1-21, MISO when SPI0 in use - RPI_V2_GPIO_P1_22 = 25, ///< Version 2, Pin P1-22 - RPI_V2_GPIO_P1_23 = 11, ///< Version 2, Pin P1-23, CLK when SPI0 in use - RPI_V2_GPIO_P1_24 = 8, ///< Version 2, Pin P1-24, CE0 when SPI0 in use - RPI_V2_GPIO_P1_26 = 7, ///< Version 2, Pin P1-26, CE1 when SPI0 in use - - // RPi Version 2, new plug P5 - RPI_V2_GPIO_P5_03 = 28, ///< Version 2, Pin P5-03 - RPI_V2_GPIO_P5_04 = 29, ///< Version 2, Pin P5-04 - RPI_V2_GPIO_P5_05 = 30, ///< Version 2, Pin P5-05 - RPI_V2_GPIO_P5_06 = 31, ///< Version 2, Pin P5-06 - + RPI_GPIO_P1_03 = 0, /*!< Version 1, Pin P1-03 */ + RPI_GPIO_P1_05 = 1, /*!< Version 1, Pin P1-05 */ + RPI_GPIO_P1_07 = 4, /*!< Version 1, Pin P1-07 */ + RPI_GPIO_P1_08 = 14, /*!< Version 1, Pin P1-08, defaults to alt function 0 UART0_TXD */ + RPI_GPIO_P1_10 = 15, /*!< Version 1, Pin P1-10, defaults to alt function 0 UART0_RXD */ + RPI_GPIO_P1_11 = 17, /*!< Version 1, Pin P1-11 */ + RPI_GPIO_P1_12 = 18, /*!< Version 1, Pin P1-12, can be PWM channel 0 in ALT FUN 5 */ + RPI_GPIO_P1_13 = 21, /*!< Version 1, Pin P1-13 */ + RPI_GPIO_P1_15 = 22, /*!< Version 1, Pin P1-15 */ + RPI_GPIO_P1_16 = 23, /*!< Version 1, Pin P1-16 */ + RPI_GPIO_P1_18 = 24, /*!< Version 1, Pin P1-18 */ + RPI_GPIO_P1_19 = 10, /*!< Version 1, Pin P1-19, MOSI when SPI0 in use */ + RPI_GPIO_P1_21 = 9, /*!< Version 1, Pin P1-21, MISO when SPI0 in use */ + RPI_GPIO_P1_22 = 25, /*!< Version 1, Pin P1-22 */ + RPI_GPIO_P1_23 = 11, /*!< Version 1, Pin P1-23, CLK when SPI0 in use */ + RPI_GPIO_P1_24 = 8, /*!< Version 1, Pin P1-24, CE0 when SPI0 in use */ + RPI_GPIO_P1_26 = 7, /*!< Version 1, Pin P1-26, CE1 when SPI0 in use */ + + /* RPi Version 2 */ + RPI_V2_GPIO_P1_03 = 2, /*!< Version 2, Pin P1-03 */ + RPI_V2_GPIO_P1_05 = 3, /*!< Version 2, Pin P1-05 */ + RPI_V2_GPIO_P1_07 = 4, /*!< Version 2, Pin P1-07 */ + RPI_V2_GPIO_P1_08 = 14, /*!< Version 2, Pin P1-08, defaults to alt function 0 UART0_TXD */ + RPI_V2_GPIO_P1_10 = 15, /*!< Version 2, Pin P1-10, defaults to alt function 0 UART0_RXD */ + RPI_V2_GPIO_P1_11 = 17, /*!< Version 2, Pin P1-11 */ + RPI_V2_GPIO_P1_12 = 18, /*!< Version 2, Pin P1-12, can be PWM channel 0 in ALT FUN 5 */ + RPI_V2_GPIO_P1_13 = 27, /*!< Version 2, Pin P1-13 */ + RPI_V2_GPIO_P1_15 = 22, /*!< Version 2, Pin P1-15 */ + RPI_V2_GPIO_P1_16 = 23, /*!< Version 2, Pin P1-16 */ + RPI_V2_GPIO_P1_18 = 24, /*!< Version 2, Pin P1-18 */ + RPI_V2_GPIO_P1_19 = 10, /*!< Version 2, Pin P1-19, MOSI when SPI0 in use */ + RPI_V2_GPIO_P1_21 = 9, /*!< Version 2, Pin P1-21, MISO when SPI0 in use */ + RPI_V2_GPIO_P1_22 = 25, /*!< Version 2, Pin P1-22 */ + RPI_V2_GPIO_P1_23 = 11, /*!< Version 2, Pin P1-23, CLK when SPI0 in use */ + RPI_V2_GPIO_P1_24 = 8, /*!< Version 2, Pin P1-24, CE0 when SPI0 in use */ + RPI_V2_GPIO_P1_26 = 7, /*!< Version 2, Pin P1-26, CE1 when SPI0 in use */ + RPI_V2_GPIO_P1_29 = 5, /*!< Version 2, Pin P1-29 */ + RPI_V2_GPIO_P1_31 = 6, /*!< Version 2, Pin P1-31 */ + RPI_V2_GPIO_P1_32 = 12, /*!< Version 2, Pin P1-32 */ + RPI_V2_GPIO_P1_33 = 13, /*!< Version 2, Pin P1-33 */ + RPI_V2_GPIO_P1_35 = 19, /*!< Version 2, Pin P1-35 */ + RPI_V2_GPIO_P1_36 = 16, /*!< Version 2, Pin P1-36 */ + RPI_V2_GPIO_P1_37 = 26, /*!< Version 2, Pin P1-37 */ + RPI_V2_GPIO_P1_38 = 20, /*!< Version 2, Pin P1-38 */ + RPI_V2_GPIO_P1_40 = 21, /*!< Version 2, Pin P1-40 */ + + /* RPi Version 2, new plug P5 */ + RPI_V2_GPIO_P5_03 = 28, /*!< Version 2, Pin P5-03 */ + RPI_V2_GPIO_P5_04 = 29, /*!< Version 2, Pin P5-04 */ + RPI_V2_GPIO_P5_05 = 30, /*!< Version 2, Pin P5-05 */ + RPI_V2_GPIO_P5_06 = 31, /*!< Version 2, Pin P5-06 */ + + /* RPi B+ J8 header, also RPi 2 40 pin GPIO header */ + RPI_BPLUS_GPIO_J8_03 = 2, /*!< B+, Pin J8-03 */ + RPI_BPLUS_GPIO_J8_05 = 3, /*!< B+, Pin J8-05 */ + RPI_BPLUS_GPIO_J8_07 = 4, /*!< B+, Pin J8-07 */ + RPI_BPLUS_GPIO_J8_08 = 14, /*!< B+, Pin J8-08, defaults to alt function 0 UART0_TXD */ + RPI_BPLUS_GPIO_J8_10 = 15, /*!< B+, Pin J8-10, defaults to alt function 0 UART0_RXD */ + RPI_BPLUS_GPIO_J8_11 = 17, /*!< B+, Pin J8-11 */ + RPI_BPLUS_GPIO_J8_12 = 18, /*!< B+, Pin J8-12, can be PWM channel 0 in ALT FUN 5 */ + RPI_BPLUS_GPIO_J8_13 = 27, /*!< B+, Pin J8-13 */ + RPI_BPLUS_GPIO_J8_15 = 22, /*!< B+, Pin J8-15 */ + RPI_BPLUS_GPIO_J8_16 = 23, /*!< B+, Pin J8-16 */ + RPI_BPLUS_GPIO_J8_18 = 24, /*!< B+, Pin J8-18 */ + RPI_BPLUS_GPIO_J8_19 = 10, /*!< B+, Pin J8-19, MOSI when SPI0 in use */ + RPI_BPLUS_GPIO_J8_21 = 9, /*!< B+, Pin J8-21, MISO when SPI0 in use */ + RPI_BPLUS_GPIO_J8_22 = 25, /*!< B+, Pin J8-22 */ + RPI_BPLUS_GPIO_J8_23 = 11, /*!< B+, Pin J8-23, CLK when SPI0 in use */ + RPI_BPLUS_GPIO_J8_24 = 8, /*!< B+, Pin J8-24, CE0 when SPI0 in use */ + RPI_BPLUS_GPIO_J8_26 = 7, /*!< B+, Pin J8-26, CE1 when SPI0 in use */ + RPI_BPLUS_GPIO_J8_29 = 5, /*!< B+, Pin J8-29, */ + RPI_BPLUS_GPIO_J8_31 = 6, /*!< B+, Pin J8-31, */ + RPI_BPLUS_GPIO_J8_32 = 12, /*!< B+, Pin J8-32, */ + RPI_BPLUS_GPIO_J8_33 = 13, /*!< B+, Pin J8-33, */ + RPI_BPLUS_GPIO_J8_35 = 19, /*!< B+, Pin J8-35, */ + RPI_BPLUS_GPIO_J8_36 = 16, /*!< B+, Pin J8-36, */ + RPI_BPLUS_GPIO_J8_37 = 26, /*!< B+, Pin J8-37, */ + RPI_BPLUS_GPIO_J8_38 = 20, /*!< B+, Pin J8-38, */ + RPI_BPLUS_GPIO_J8_40 = 21 /*!< B+, Pin J8-40, */ } RPiGPIOPin; -// Defines for SPI -// GPIO register offsets from BCM2835_SPI0_BASE. -// Offsets into the SPI Peripheral block in bytes per 10.5 SPI Register Map -#define BCM2835_SPI0_CS 0x0000 ///< SPI Master Control and Status -#define BCM2835_SPI0_FIFO 0x0004 ///< SPI Master TX and RX FIFOs -#define BCM2835_SPI0_CLK 0x0008 ///< SPI Master Clock Divider -#define BCM2835_SPI0_DLEN 0x000c ///< SPI Master Data Length -#define BCM2835_SPI0_LTOH 0x0010 ///< SPI LOSSI mode TOH -#define BCM2835_SPI0_DC 0x0014 ///< SPI DMA DREQ Controls - -// Register masks for SPI0_CS -#define BCM2835_SPI0_CS_LEN_LONG 0x02000000 ///< Enable Long data word in Lossi mode if DMA_LEN is set -#define BCM2835_SPI0_CS_DMA_LEN 0x01000000 ///< Enable DMA mode in Lossi mode -#define BCM2835_SPI0_CS_CSPOL2 0x00800000 ///< Chip Select 2 Polarity -#define BCM2835_SPI0_CS_CSPOL1 0x00400000 ///< Chip Select 1 Polarity -#define BCM2835_SPI0_CS_CSPOL0 0x00200000 ///< Chip Select 0 Polarity -#define BCM2835_SPI0_CS_RXF 0x00100000 ///< RXF - RX FIFO Full -#define BCM2835_SPI0_CS_RXR 0x00080000 ///< RXR RX FIFO needs Reading ( full) -#define BCM2835_SPI0_CS_TXD 0x00040000 ///< TXD TX FIFO can accept Data -#define BCM2835_SPI0_CS_RXD 0x00020000 ///< RXD RX FIFO contains Data -#define BCM2835_SPI0_CS_DONE 0x00010000 ///< Done transfer Done -#define BCM2835_SPI0_CS_TE_EN 0x00008000 ///< Unused -#define BCM2835_SPI0_CS_LMONO 0x00004000 ///< Unused -#define BCM2835_SPI0_CS_LEN 0x00002000 ///< LEN LoSSI enable -#define BCM2835_SPI0_CS_REN 0x00001000 ///< REN Read Enable -#define BCM2835_SPI0_CS_ADCS 0x00000800 ///< ADCS Automatically Deassert Chip Select -#define BCM2835_SPI0_CS_INTR 0x00000400 ///< INTR Interrupt on RXR -#define BCM2835_SPI0_CS_INTD 0x00000200 ///< INTD Interrupt on Done -#define BCM2835_SPI0_CS_DMAEN 0x00000100 ///< DMAEN DMA Enable -#define BCM2835_SPI0_CS_TA 0x00000080 ///< Transfer Active -#define BCM2835_SPI0_CS_CSPOL 0x00000040 ///< Chip Select Polarity -#define BCM2835_SPI0_CS_CLEAR 0x00000030 ///< Clear FIFO Clear RX and TX -#define BCM2835_SPI0_CS_CLEAR_RX 0x00000020 ///< Clear FIFO Clear RX -#define BCM2835_SPI0_CS_CLEAR_TX 0x00000010 ///< Clear FIFO Clear TX -#define BCM2835_SPI0_CS_CPOL 0x00000008 ///< Clock Polarity -#define BCM2835_SPI0_CS_CPHA 0x00000004 ///< Clock Phase -#define BCM2835_SPI0_CS_CS 0x00000003 ///< Chip Select - -/// \brief bcm2835SPIBitOrder SPI Bit order -/// Specifies the SPI data bit ordering for bcm2835_spi_setBitOrder() +/* Defines for SPI + GPIO register offsets from BCM2835_SPI0_BASE. + Offsets into the SPI Peripheral block in bytes per 10.5 SPI Register Map +*/ +#define BCM2835_SPI0_CS 0x0000 /*!< SPI Master Control and Status */ +#define BCM2835_SPI0_FIFO 0x0004 /*!< SPI Master TX and RX FIFOs */ +#define BCM2835_SPI0_CLK 0x0008 /*!< SPI Master Clock Divider */ +#define BCM2835_SPI0_DLEN 0x000c /*!< SPI Master Data Length */ +#define BCM2835_SPI0_LTOH 0x0010 /*!< SPI LOSSI mode TOH */ +#define BCM2835_SPI0_DC 0x0014 /*!< SPI DMA DREQ Controls */ + +/* Register masks for SPI0_CS */ +#define BCM2835_SPI0_CS_LEN_LONG 0x02000000 /*!< Enable Long data word in Lossi mode if DMA_LEN is set */ +#define BCM2835_SPI0_CS_DMA_LEN 0x01000000 /*!< Enable DMA mode in Lossi mode */ +#define BCM2835_SPI0_CS_CSPOL2 0x00800000 /*!< Chip Select 2 Polarity */ +#define BCM2835_SPI0_CS_CSPOL1 0x00400000 /*!< Chip Select 1 Polarity */ +#define BCM2835_SPI0_CS_CSPOL0 0x00200000 /*!< Chip Select 0 Polarity */ +#define BCM2835_SPI0_CS_RXF 0x00100000 /*!< RXF - RX FIFO Full */ +#define BCM2835_SPI0_CS_RXR 0x00080000 /*!< RXR RX FIFO needs Reading (full) */ +#define BCM2835_SPI0_CS_TXD 0x00040000 /*!< TXD TX FIFO can accept Data */ +#define BCM2835_SPI0_CS_RXD 0x00020000 /*!< RXD RX FIFO contains Data */ +#define BCM2835_SPI0_CS_DONE 0x00010000 /*!< Done transfer Done */ +#define BCM2835_SPI0_CS_TE_EN 0x00008000 /*!< Unused */ +#define BCM2835_SPI0_CS_LMONO 0x00004000 /*!< Unused */ +#define BCM2835_SPI0_CS_LEN 0x00002000 /*!< LEN LoSSI enable */ +#define BCM2835_SPI0_CS_REN 0x00001000 /*!< REN Read Enable */ +#define BCM2835_SPI0_CS_ADCS 0x00000800 /*!< ADCS Automatically Deassert Chip Select */ +#define BCM2835_SPI0_CS_INTR 0x00000400 /*!< INTR Interrupt on RXR */ +#define BCM2835_SPI0_CS_INTD 0x00000200 /*!< INTD Interrupt on Done */ +#define BCM2835_SPI0_CS_DMAEN 0x00000100 /*!< DMAEN DMA Enable */ +#define BCM2835_SPI0_CS_TA 0x00000080 /*!< Transfer Active */ +#define BCM2835_SPI0_CS_CSPOL 0x00000040 /*!< Chip Select Polarity */ +#define BCM2835_SPI0_CS_CLEAR 0x00000030 /*!< Clear FIFO Clear RX and TX */ +#define BCM2835_SPI0_CS_CLEAR_RX 0x00000020 /*!< Clear FIFO Clear RX */ +#define BCM2835_SPI0_CS_CLEAR_TX 0x00000010 /*!< Clear FIFO Clear TX */ +#define BCM2835_SPI0_CS_CPOL 0x00000008 /*!< Clock Polarity */ +#define BCM2835_SPI0_CS_CPHA 0x00000004 /*!< Clock Phase */ +#define BCM2835_SPI0_CS_CS 0x00000003 /*!< Chip Select */ + +/*! \brief bcm2835SPIBitOrder SPI Bit order + Specifies the SPI data bit ordering for bcm2835_spi_setBitOrder() +*/ typedef enum { - BCM2835_SPI_BIT_ORDER_LSBFIRST = 0, ///< LSB First - BCM2835_SPI_BIT_ORDER_MSBFIRST = 1 ///< MSB First + BCM2835_SPI_BIT_ORDER_LSBFIRST = 0, /*!< LSB First */ + BCM2835_SPI_BIT_ORDER_MSBFIRST = 1 /*!< MSB First */ }bcm2835SPIBitOrder; -/// \brief SPI Data mode -/// Specify the SPI data mode to be passed to bcm2835_spi_setDataMode() +/*! \brief SPI Data mode + Specify the SPI data mode to be passed to bcm2835_spi_setDataMode() +*/ typedef enum { - BCM2835_SPI_MODE0 = 0, ///< CPOL = 0, CPHA = 0 - BCM2835_SPI_MODE1 = 1, ///< CPOL = 0, CPHA = 1 - BCM2835_SPI_MODE2 = 2, ///< CPOL = 1, CPHA = 0 - BCM2835_SPI_MODE3 = 3, ///< CPOL = 1, CPHA = 1 + BCM2835_SPI_MODE0 = 0, /*!< CPOL = 0, CPHA = 0 */ + BCM2835_SPI_MODE1 = 1, /*!< CPOL = 0, CPHA = 1 */ + BCM2835_SPI_MODE2 = 2, /*!< CPOL = 1, CPHA = 0 */ + BCM2835_SPI_MODE3 = 3 /*!< CPOL = 1, CPHA = 1 */ }bcm2835SPIMode; -/// \brief bcm2835SPIChipSelect -/// Specify the SPI chip select pin(s) +/*! \brief bcm2835SPIChipSelect + Specify the SPI chip select pin(s) +*/ typedef enum { - 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 + 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 -/// Specifies the divider used to generate the SPI clock from the system clock. -/// Figures below give the divider, clock period and clock frequency. -/// Clock divided is based on nominal base clock rate of 250MHz -/// It is reported that (contrary to the documentation) any even divider may used. -/// The frequencies shown for each divider have been confirmed by measurement +/*! \brief bcm2835SPIClockDivider + Specifies the divider used to generate the SPI clock from the system clock. + Figures below give the divider, clock period and clock frequency. + Clock divided is based on nominal base clock rate of 250MHz + It is reported that (contrary to the documentation) any even divider may used. + The frequencies shown for each divider have been confirmed by measurement. +*/ typedef enum { - BCM2835_SPI_CLOCK_DIVIDER_65536 = 0, ///< 65536 = 262.144us = 3.814697260kHz - BCM2835_SPI_CLOCK_DIVIDER_32768 = 32768, ///< 32768 = 131.072us = 7.629394531kHz - BCM2835_SPI_CLOCK_DIVIDER_16384 = 16384, ///< 16384 = 65.536us = 15.25878906kHz - BCM2835_SPI_CLOCK_DIVIDER_8192 = 8192, ///< 8192 = 32.768us = 30/51757813kHz - BCM2835_SPI_CLOCK_DIVIDER_4096 = 4096, ///< 4096 = 16.384us = 61.03515625kHz - BCM2835_SPI_CLOCK_DIVIDER_2048 = 2048, ///< 2048 = 8.192us = 122.0703125kHz - BCM2835_SPI_CLOCK_DIVIDER_1024 = 1024, ///< 1024 = 4.096us = 244.140625kHz - BCM2835_SPI_CLOCK_DIVIDER_512 = 512, ///< 512 = 2.048us = 488.28125kHz - BCM2835_SPI_CLOCK_DIVIDER_256 = 256, ///< 256 = 1.024us = 976.5625MHz - BCM2835_SPI_CLOCK_DIVIDER_128 = 128, ///< 128 = 512ns = = 1.953125MHz - BCM2835_SPI_CLOCK_DIVIDER_64 = 64, ///< 64 = 256ns = 3.90625MHz - BCM2835_SPI_CLOCK_DIVIDER_32 = 32, ///< 32 = 128ns = 7.8125MHz - BCM2835_SPI_CLOCK_DIVIDER_16 = 16, ///< 16 = 64ns = 15.625MHz - BCM2835_SPI_CLOCK_DIVIDER_8 = 8, ///< 8 = 32ns = 31.25MHz - BCM2835_SPI_CLOCK_DIVIDER_4 = 4, ///< 4 = 16ns = 62.5MHz - BCM2835_SPI_CLOCK_DIVIDER_2 = 2, ///< 2 = 8ns = 125MHz, fastest you can get - BCM2835_SPI_CLOCK_DIVIDER_1 = 1, ///< 1 = 262.144us = 3.814697260kHz, same as 0/65536 + BCM2835_SPI_CLOCK_DIVIDER_65536 = 0, /*!< 65536 = 262.144us = 3.814697260kHz */ + BCM2835_SPI_CLOCK_DIVIDER_32768 = 32768, /*!< 32768 = 131.072us = 7.629394531kHz */ + BCM2835_SPI_CLOCK_DIVIDER_16384 = 16384, /*!< 16384 = 65.536us = 15.25878906kHz */ + BCM2835_SPI_CLOCK_DIVIDER_8192 = 8192, /*!< 8192 = 32.768us = 30/51757813kHz */ + BCM2835_SPI_CLOCK_DIVIDER_4096 = 4096, /*!< 4096 = 16.384us = 61.03515625kHz */ + BCM2835_SPI_CLOCK_DIVIDER_2048 = 2048, /*!< 2048 = 8.192us = 122.0703125kHz */ + BCM2835_SPI_CLOCK_DIVIDER_1024 = 1024, /*!< 1024 = 4.096us = 244.140625kHz */ + BCM2835_SPI_CLOCK_DIVIDER_512 = 512, /*!< 512 = 2.048us = 488.28125kHz */ + BCM2835_SPI_CLOCK_DIVIDER_256 = 256, /*!< 256 = 1.024us = 976.5625kHz */ + BCM2835_SPI_CLOCK_DIVIDER_128 = 128, /*!< 128 = 512ns = = 1.953125MHz */ + BCM2835_SPI_CLOCK_DIVIDER_64 = 64, /*!< 64 = 256ns = 3.90625MHz */ + BCM2835_SPI_CLOCK_DIVIDER_32 = 32, /*!< 32 = 128ns = 7.8125MHz */ + BCM2835_SPI_CLOCK_DIVIDER_16 = 16, /*!< 16 = 64ns = 15.625MHz */ + BCM2835_SPI_CLOCK_DIVIDER_8 = 8, /*!< 8 = 32ns = 31.25MHz */ + BCM2835_SPI_CLOCK_DIVIDER_4 = 4, /*!< 4 = 16ns = 62.5MHz */ + BCM2835_SPI_CLOCK_DIVIDER_2 = 2, /*!< 2 = 8ns = 125MHz, fastest you can get */ + BCM2835_SPI_CLOCK_DIVIDER_1 = 1 /*!< 1 = 262.144us = 3.814697260kHz, same as 0/65536 */ } bcm2835SPIClockDivider; -// Defines for I2C -// GPIO register offsets from BCM2835_BSC*_BASE. -// Offsets into the BSC Peripheral block in bytes per 3.1 BSC Register Map -#define BCM2835_BSC_C 0x0000 ///< BSC Master Control -#define BCM2835_BSC_S 0x0004 ///< BSC Master Status -#define BCM2835_BSC_DLEN 0x0008 ///< BSC Master Data Length -#define BCM2835_BSC_A 0x000c ///< BSC Master Slave Address -#define BCM2835_BSC_FIFO 0x0010 ///< BSC Master Data FIFO -#define BCM2835_BSC_DIV 0x0014 ///< BSC Master Clock Divider -#define BCM2835_BSC_DEL 0x0018 ///< BSC Master Data Delay -#define BCM2835_BSC_CLKT 0x001c ///< BSC Master Clock Stretch Timeout - -// Register masks for BSC_C -#define BCM2835_BSC_C_I2CEN 0x00008000 ///< I2C Enable, 0 = disabled, 1 = enabled -#define BCM2835_BSC_C_INTR 0x00000400 ///< Interrupt on RX -#define BCM2835_BSC_C_INTT 0x00000200 ///< Interrupt on TX -#define BCM2835_BSC_C_INTD 0x00000100 ///< Interrupt on DONE -#define BCM2835_BSC_C_ST 0x00000080 ///< Start transfer, 1 = Start a new transfer -#define BCM2835_BSC_C_CLEAR_1 0x00000020 ///< Clear FIFO Clear -#define BCM2835_BSC_C_CLEAR_2 0x00000010 ///< Clear FIFO Clear -#define BCM2835_BSC_C_READ 0x00000001 ///< Read transfer - -// Register masks for BSC_S -#define BCM2835_BSC_S_CLKT 0x00000200 ///< Clock stretch timeout -#define BCM2835_BSC_S_ERR 0x00000100 ///< ACK error -#define BCM2835_BSC_S_RXF 0x00000080 ///< RXF FIFO full, 0 = FIFO is not full, 1 = FIFO is full -#define BCM2835_BSC_S_TXE 0x00000040 ///< TXE FIFO full, 0 = FIFO is not full, 1 = FIFO is full -#define BCM2835_BSC_S_RXD 0x00000020 ///< RXD FIFO contains data -#define BCM2835_BSC_S_TXD 0x00000010 ///< TXD FIFO can accept data -#define BCM2835_BSC_S_RXR 0x00000008 ///< RXR FIFO needs reading (full) -#define BCM2835_BSC_S_TXW 0x00000004 ///< TXW FIFO needs writing (full) -#define BCM2835_BSC_S_DONE 0x00000002 ///< Transfer DONE -#define BCM2835_BSC_S_TA 0x00000001 ///< Transfer Active - -#define BCM2835_BSC_FIFO_SIZE 16 ///< BSC FIFO size - -/// \brief bcm2835I2CClockDivider -/// Specifies the divider used to generate the I2C clock from the system clock. -/// Clock divided is based on nominal base clock rate of 250MHz +/* Defines for I2C + GPIO register offsets from BCM2835_BSC*_BASE. + Offsets into the BSC Peripheral block in bytes per 3.1 BSC Register Map +*/ +#define BCM2835_BSC_C 0x0000 /*!< BSC Master Control */ +#define BCM2835_BSC_S 0x0004 /*!< BSC Master Status */ +#define BCM2835_BSC_DLEN 0x0008 /*!< BSC Master Data Length */ +#define BCM2835_BSC_A 0x000c /*!< BSC Master Slave Address */ +#define BCM2835_BSC_FIFO 0x0010 /*!< BSC Master Data FIFO */ +#define BCM2835_BSC_DIV 0x0014 /*!< BSC Master Clock Divider */ +#define BCM2835_BSC_DEL 0x0018 /*!< BSC Master Data Delay */ +#define BCM2835_BSC_CLKT 0x001c /*!< BSC Master Clock Stretch Timeout */ + +/* Register masks for BSC_C */ +#define BCM2835_BSC_C_I2CEN 0x00008000 /*!< I2C Enable, 0 = disabled, 1 = enabled */ +#define BCM2835_BSC_C_INTR 0x00000400 /*!< Interrupt on RX */ +#define BCM2835_BSC_C_INTT 0x00000200 /*!< Interrupt on TX */ +#define BCM2835_BSC_C_INTD 0x00000100 /*!< Interrupt on DONE */ +#define BCM2835_BSC_C_ST 0x00000080 /*!< Start transfer, 1 = Start a new transfer */ +#define BCM2835_BSC_C_CLEAR_1 0x00000020 /*!< Clear FIFO Clear */ +#define BCM2835_BSC_C_CLEAR_2 0x00000010 /*!< Clear FIFO Clear */ +#define BCM2835_BSC_C_READ 0x00000001 /*!< Read transfer */ + +/* Register masks for BSC_S */ +#define BCM2835_BSC_S_CLKT 0x00000200 /*!< Clock stretch timeout */ +#define BCM2835_BSC_S_ERR 0x00000100 /*!< ACK error */ +#define BCM2835_BSC_S_RXF 0x00000080 /*!< RXF FIFO full, 0 = FIFO is not full, 1 = FIFO is full */ +#define BCM2835_BSC_S_TXE 0x00000040 /*!< TXE FIFO full, 0 = FIFO is not full, 1 = FIFO is full */ +#define BCM2835_BSC_S_RXD 0x00000020 /*!< RXD FIFO contains data */ +#define BCM2835_BSC_S_TXD 0x00000010 /*!< TXD FIFO can accept data */ +#define BCM2835_BSC_S_RXR 0x00000008 /*!< RXR FIFO needs reading (full) */ +#define BCM2835_BSC_S_TXW 0x00000004 /*!< TXW FIFO needs writing (full) */ +#define BCM2835_BSC_S_DONE 0x00000002 /*!< Transfer DONE */ +#define BCM2835_BSC_S_TA 0x00000001 /*!< Transfer Active */ + +#define BCM2835_BSC_FIFO_SIZE 16 /*!< BSC FIFO size */ + +/*! \brief bcm2835I2CClockDivider + Specifies the divider used to generate the I2C clock from the system clock. + Clock divided is based on nominal base clock rate of 250MHz +*/ typedef enum { - BCM2835_I2C_CLOCK_DIVIDER_2500 = 2500, ///< 2500 = 10us = 100 kHz - BCM2835_I2C_CLOCK_DIVIDER_626 = 626, ///< 622 = 2.504us = 399.3610 kHz - BCM2835_I2C_CLOCK_DIVIDER_150 = 150, ///< 150 = 60ns = 1.666 MHz (default at reset) - BCM2835_I2C_CLOCK_DIVIDER_148 = 148, ///< 148 = 59ns = 1.689 MHz + BCM2835_I2C_CLOCK_DIVIDER_2500 = 2500, /*!< 2500 = 10us = 100 kHz */ + BCM2835_I2C_CLOCK_DIVIDER_626 = 626, /*!< 622 = 2.504us = 399.3610 kHz */ + BCM2835_I2C_CLOCK_DIVIDER_150 = 150, /*!< 150 = 60ns = 1.666 MHz (default at reset) */ + BCM2835_I2C_CLOCK_DIVIDER_148 = 148 /*!< 148 = 59ns = 1.689 MHz */ } bcm2835I2CClockDivider; -/// \brief bcm2835I2CReasonCodes -/// Specifies the reason codes for the bcm2835_i2c_write and bcm2835_i2c_read functions. +/*! \brief bcm2835I2CReasonCodes + Specifies the reason codes for the bcm2835_i2c_write and bcm2835_i2c_read functions. +*/ typedef enum { - BCM2835_I2C_REASON_OK = 0x00, ///< Success - BCM2835_I2C_REASON_ERROR_NACK = 0x01, ///< Received a NACK - BCM2835_I2C_REASON_ERROR_CLKT = 0x02, ///< Received Clock Stretch Timeout - BCM2835_I2C_REASON_ERROR_DATA = 0x04, ///< Not all data is sent / received + BCM2835_I2C_REASON_OK = 0x00, /*!< Success */ + BCM2835_I2C_REASON_ERROR_NACK = 0x01, /*!< Received a NACK */ + BCM2835_I2C_REASON_ERROR_CLKT = 0x02, /*!< Received Clock Stretch Timeout */ + BCM2835_I2C_REASON_ERROR_DATA = 0x04 /*!< Not all data is sent / received */ } bcm2835I2CReasonCodes; -// Defines for ST -// GPIO register offsets from BCM2835_ST_BASE. -// Offsets into the ST Peripheral block in bytes per 12.1 System Timer Registers -// The System Timer peripheral provides four 32-bit timer channels and a single 64-bit free running counter. -// BCM2835_ST_CLO is the System Timer Counter Lower bits register. -// The system timer free-running counter lower register is a read-only register that returns the current value -// of the lower 32-bits of the free running counter. -// BCM2835_ST_CHI is the System Timer Counter Upper bits register. -// The system timer free-running counter upper register is a read-only register that returns the current value -// of the upper 32-bits of the free running counter. -#define BCM2835_ST_CS 0x0000 ///< System Timer Control/Status -#define BCM2835_ST_CLO 0x0004 ///< System Timer Counter Lower 32 bits -#define BCM2835_ST_CHI 0x0008 ///< System Timer Counter Upper 32 bits - -/// @} - - -// Defines for PWM, word offsets (ie 4 byte multiples) +/* Defines for ST + GPIO register offsets from BCM2835_ST_BASE. + Offsets into the ST Peripheral block in bytes per 12.1 System Timer Registers + The System Timer peripheral provides four 32-bit timer channels and a single 64-bit free running counter. + BCM2835_ST_CLO is the System Timer Counter Lower bits register. + The system timer free-running counter lower register is a read-only register that returns the current value + of the lower 32-bits of the free running counter. + BCM2835_ST_CHI is the System Timer Counter Upper bits register. + The system timer free-running counter upper register is a read-only register that returns the current value + of the upper 32-bits of the free running counter. +*/ +#define BCM2835_ST_CS 0x0000 /*!< System Timer Control/Status */ +#define BCM2835_ST_CLO 0x0004 /*!< System Timer Counter Lower 32 bits */ +#define BCM2835_ST_CHI 0x0008 /*!< System Timer Counter Upper 32 bits */ + +/*! @} */ + + +/* Defines for PWM, word offsets (ie 4 byte multiples) */ #define BCM2835_PWM_CONTROL 0 #define BCM2835_PWM_STATUS 1 #define BCM2835_PWM_DMAC 2 @@ -707,54 +964,51 @@ typedef enum #define BCM2835_PWM1_RANGE 8 #define BCM2835_PWM1_DATA 9 -// Defines for PWM Clock, word offsets (ie 4 byte multiples) +/* Defines for PWM Clock, word offsets (ie 4 byte multiples) */ #define BCM2835_PWMCLK_CNTL 40 #define BCM2835_PWMCLK_DIV 41 -#define BCM2835_PWM_PASSWRD (0x5A << 24) ///< Password to enable setting PWM clock - -#define BCM2835_PWM1_MS_MODE 0x8000 ///< Run in Mark/Space mode -#define BCM2835_PWM1_USEFIFO 0x2000 ///< Data from FIFO -#define BCM2835_PWM1_REVPOLAR 0x1000 ///< Reverse polarity -#define BCM2835_PWM1_OFFSTATE 0x0800 ///< Ouput Off state -#define BCM2835_PWM1_REPEATFF 0x0400 ///< Repeat last value if FIFO empty -#define BCM2835_PWM1_SERIAL 0x0200 ///< Run in serial mode -#define BCM2835_PWM1_ENABLE 0x0100 ///< Channel Enable - -#define BCM2835_PWM0_MS_MODE 0x0080 ///< Run in Mark/Space mode -#define BCM2835_PWM_CLEAR_FIFO 0x0040 ///< Clear FIFO -#define BCM2835_PWM0_USEFIFO 0x0020 ///< Data from FIFO -#define BCM2835_PWM0_REVPOLAR 0x0010 ///< Reverse polarity -#define BCM2835_PWM0_OFFSTATE 0x0008 ///< Ouput Off state -#define BCM2835_PWM0_REPEATFF 0x0004 ///< Repeat last value if FIFO empty -#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. -/// Clock divided is based on nominal PWM base clock rate of 19.2MHz -/// The frequencies shown for each divider have been confirmed by measurement +#define BCM2835_PWM_PASSWRD (0x5A << 24) /*!< Password to enable setting PWM clock */ + +#define BCM2835_PWM1_MS_MODE 0x8000 /*!< Run in Mark/Space mode */ +#define BCM2835_PWM1_USEFIFO 0x2000 /*!< Data from FIFO */ +#define BCM2835_PWM1_REVPOLAR 0x1000 /*!< Reverse polarity */ +#define BCM2835_PWM1_OFFSTATE 0x0800 /*!< Ouput Off state */ +#define BCM2835_PWM1_REPEATFF 0x0400 /*!< Repeat last value if FIFO empty */ +#define BCM2835_PWM1_SERIAL 0x0200 /*!< Run in serial mode */ +#define BCM2835_PWM1_ENABLE 0x0100 /*!< Channel Enable */ + +#define BCM2835_PWM0_MS_MODE 0x0080 /*!< Run in Mark/Space mode */ +#define BCM2835_PWM_CLEAR_FIFO 0x0040 /*!< Clear FIFO */ +#define BCM2835_PWM0_USEFIFO 0x0020 /*!< Data from FIFO */ +#define BCM2835_PWM0_REVPOLAR 0x0010 /*!< Reverse polarity */ +#define BCM2835_PWM0_OFFSTATE 0x0008 /*!< Ouput Off state */ +#define BCM2835_PWM0_REPEATFF 0x0004 /*!< Repeat last value if FIFO empty */ +#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. + Clock divided is based on nominal PWM base clock rate of 19.2MHz + 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 - BCM2835_PWM_CLOCK_DIVIDER_256 = 256, ///< 256 = 75kHz - BCM2835_PWM_CLOCK_DIVIDER_128 = 128, ///< 128 = 150kHz - BCM2835_PWM_CLOCK_DIVIDER_64 = 64, ///< 64 = 300kHz - BCM2835_PWM_CLOCK_DIVIDER_32 = 32, ///< 32 = 600.0kHz - BCM2835_PWM_CLOCK_DIVIDER_16 = 16, ///< 16 = 1.2MHz - BCM2835_PWM_CLOCK_DIVIDER_8 = 8, ///< 8 = 2.4MHz - BCM2835_PWM_CLOCK_DIVIDER_4 = 4, ///< 4 = 4.8MHz - BCM2835_PWM_CLOCK_DIVIDER_2 = 2, ///< 2 = 9.6MHz, fastest you can get - BCM2835_PWM_CLOCK_DIVIDER_1 = 1, ///< 1 = 4.6875kHz, same as divider 4096 + 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 */ + BCM2835_PWM_CLOCK_DIVIDER_256 = 256, /*!< 256 = 75kHz */ + BCM2835_PWM_CLOCK_DIVIDER_128 = 128, /*!< 128 = 150kHz */ + BCM2835_PWM_CLOCK_DIVIDER_64 = 64, /*!< 64 = 300kHz */ + BCM2835_PWM_CLOCK_DIVIDER_32 = 32, /*!< 32 = 600.0kHz */ + BCM2835_PWM_CLOCK_DIVIDER_16 = 16, /*!< 16 = 1.2MHz */ + BCM2835_PWM_CLOCK_DIVIDER_8 = 8, /*!< 8 = 2.4MHz */ + BCM2835_PWM_CLOCK_DIVIDER_4 = 4, /*!< 4 = 4.8MHz */ + BCM2835_PWM_CLOCK_DIVIDER_2 = 2, /*!< 2 = 9.6MHz, fastest you can get */ + BCM2835_PWM_CLOCK_DIVIDER_1 = 1 /*!< 1 = 4.6875kHz, same as divider 4096 */ } bcm2835PWMClockDivider; -// Historical name compatibility +/* Historical name compatibility */ #ifndef BCM2835_NO_DELAY_COMPATIBILITY #define delay(x) bcm2835_delay(x) #define delayMicroseconds(x) bcm2835_delayMicroseconds(x) @@ -764,531 +1018,654 @@ typedef enum extern "C" { #endif - /// \defgroup init Library initialisation and management - /// These functions allow you to intialise and control the bcm2835 library - /// @{ - - /// Initialise the library by opening /dev/mem and getting pointers to the - /// internal memory for BCM 2835 device registers. You must call this (successfully) - /// before calling any other - /// functions in this library (except bcm2835_set_debug). - /// If bcm2835_init() fails by returning 0, - /// calling any other function may result in crashes or other failures. - /// Prints messages to stderr in case of errors. - /// \return 1 if successful else 0 + /*! \defgroup init Library initialisation and management + These functions allow you to intialise and control the bcm2835 library + @{ + */ + + /*! Initialise the library by opening /dev/mem (if you are root) + or /dev/gpiomem (if you are not) + and getting pointers to the + internal memory for BCM 2835 device registers. You must call this (successfully) + before calling any other + functions in this library (except bcm2835_set_debug). + If bcm2835_init() fails by returning 0, + calling any other function may result in crashes or other failures. + If bcm2835_init() succeeds but you are not running as root, then only gpio operations + are permitted, and calling any other functions may result in crashes or other failures. . + Prints messages to stderr in case of errors. + \return 1 if successful else 0 + */ extern int bcm2835_init(void); - /// Close the library, deallocating any allocated memory and closing /dev/mem - /// \return 1 if successful else 0 + /*! Close the library, deallocating any allocated memory and closing /dev/mem + \return 1 if successful else 0 + */ extern int bcm2835_close(void); - /// Sets the debug level of the library. - /// A value of 1 prevents mapping to /dev/mem, and makes the library print out - /// what it would do, rather than accessing the GPIO registers. - /// A value of 0, the default, causes normal operation. - /// Call this before calling bcm2835_init(); - /// \param[in] debug The new debug level. 1 means debug + /*! Sets the debug level of the library. + A value of 1 prevents mapping to /dev/mem, and makes the library print out + what it would do, rather than accessing the GPIO registers. + A value of 0, the default, causes normal operation. + Call this before calling bcm2835_init(); + \param[in] debug The new debug level. 1 means debug + */ extern void bcm2835_set_debug(uint8_t debug); - /// @} // end of init - - /// \defgroup lowlevel Low level register access - /// These functions provide low level register access, and should not generally - /// need to be used - /// - /// @{ - - /// 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 + /*! Returns the version number of the library, same as BCM2835_VERSION + \return the current library version number + */ + extern unsigned int bcm2835_version(void); + + /*! @} */ + + /*! \defgroup lowlevel Low level register access + These functions provide low level register access, and should not generally + need to be used + + @{ + */ + + /*! 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 WITH a memory barrier before and after each read. + This is safe, but slow. The MB before protects this read from any in-flight reads that didn't + use a MB. The MB after protects subsequent reads from another peripheral. + + \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); + /*! Reads 32 bit value from a peripheral address WITHOUT the read barriers + You should only use this when: + o your code has previously called bcm2835_peri_read() for a register + within the same peripheral, and no read or write to another peripheral has occurred since. + o your code has called bcm2835_memory_barrier() since the last access to ANOTHER peripheral. - /// Reads 32 bit value from a peripheral address without the read barrier - /// You should only use this when your code has previously called bcm2835_peri_read() - /// within the same peripheral, and no other peripheral access has occurred since. - /// \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 + \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); - /// Writes 32 bit value from a peripheral address - /// The write 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. - /// \param[in] value The 32 bit value to write - /// \sa Physical Addresses + /*! Writes 32 bit value from a peripheral address WITH a memory barrier before and after each write + This is safe, but slow. The MB before ensures that any in-flight write to another peripheral + completes before this write is issued. The MB after ensures that subsequent reads and writes + to another peripheral will see the effect of this write. + + This is a tricky optimization; if you aren't sure, use the barrier version. + + \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); - /// 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() - /// within the same peripheral, and no other peripheral access has occurred since. - /// \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); + /*! Writes 32 bit value from a peripheral address without the write barrier + You should only use this when: + o your code has previously called bcm2835_peri_write() for a register + within the same peripheral, and no other peripheral access has occurred since. + o your code has called bcm2835_memory_barrier() since the last access to ANOTHER peripheral. - /// 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, - /// according to the bit value in value. - /// All other bits that are 0 in the mask are unaffected. - /// Use this to alter a subset of the bits in a register. - /// The write 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. - /// \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); - /// @} // end of lowlevel + This is a tricky optimization; if you aren't sure, use the barrier version. - /// \defgroup gpio GPIO register access - /// These functions allow you to control the GPIO interface. You can set the - /// function of each GPIO pin, read the input state and set the output state. - /// @{ + \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); - /// Sets the Function Select register for the given pin, which configures - /// the pin as Input, Output or one of the 6 alternate functions. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - /// \param[in] mode Mode to set the pin to, one of BCM2835_GPIO_FSEL_* from \ref bcm2835FunctionSelect + /*! Alters a number of bits in a 32 peripheral regsiter. + It reads the current valu and then alters the bits defines as 1 in mask, + according to the bit value in value. + All other bits that are 0 in the mask are unaffected. + Use this to alter a subset of the bits in a register. + Memory barriers are used. Note that this is not atomic; an interrupt + routine can cause unexpected results. + \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. + \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); + /*! @} end of lowlevel */ + + /*! \defgroup gpio GPIO register access + These functions allow you to control the GPIO interface. You can set the + function of each GPIO pin, read the input state and set the output state. + @{ + */ + + /*! Sets the Function Select register for the given pin, which configures + the pin as Input, Output or one of the 6 alternate functions. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + \param[in] mode Mode to set the pin to, one of BCM2835_GPIO_FSEL_* from \ref bcm2835FunctionSelect + */ extern void bcm2835_gpio_fsel(uint8_t pin, uint8_t mode); - /// Sets the specified pin output to - /// HIGH. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - /// \sa bcm2835_gpio_write() + /*! Sets the specified pin output to + HIGH. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + \sa bcm2835_gpio_write() + */ extern void bcm2835_gpio_set(uint8_t pin); - /// Sets the specified pin output to - /// LOW. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - /// \sa bcm2835_gpio_write() + /*! Sets the specified pin output to + LOW. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + \sa bcm2835_gpio_write() + */ extern void bcm2835_gpio_clr(uint8_t pin); - /// Sets any of the first 32 GPIO output pins specified in the mask to - /// HIGH. - /// \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - /// \sa bcm2835_gpio_write_multi() + /*! Sets any of the first 32 GPIO output pins specified in the mask to + HIGH. + \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) + \sa bcm2835_gpio_write_multi() + */ extern void bcm2835_gpio_set_multi(uint32_t mask); - /// Sets any of the first 32 GPIO output pins specified in the mask to - /// LOW. - /// \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - /// \sa bcm2835_gpio_write_multi() + /*! Sets any of the first 32 GPIO output pins specified in the mask to + LOW. + \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) + \sa bcm2835_gpio_write_multi() + */ extern void bcm2835_gpio_clr_multi(uint32_t mask); - /// Reads the current level on the specified - /// pin and returns either HIGH or LOW. Works whether or not the pin - /// is an input or an output. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - /// \return the current level either HIGH or LOW + /*! Reads the current level on the specified + pin and returns either HIGH or LOW. Works whether or not the pin + is an input or an output. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + \return the current level either HIGH or LOW + */ extern uint8_t bcm2835_gpio_lev(uint8_t pin); - /// Event Detect Status. - /// Tests whether the specified pin has detected a level or edge - /// as requested by bcm2835_gpio_ren(), bcm2835_gpio_fen(), bcm2835_gpio_hen(), - /// bcm2835_gpio_len(), bcm2835_gpio_aren(), bcm2835_gpio_afen(). - /// Clear the flag for a given pin by calling bcm2835_gpio_set_eds(pin); - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - /// \return HIGH if the event detect status for the given pin is true. + /*! Event Detect Status. + Tests whether the specified pin has detected a level or edge + as requested by bcm2835_gpio_ren(), bcm2835_gpio_fen(), bcm2835_gpio_hen(), + bcm2835_gpio_len(), bcm2835_gpio_aren(), bcm2835_gpio_afen(). + Clear the flag for a given pin by calling bcm2835_gpio_set_eds(pin); + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + \return HIGH if the event detect status for the given pin is true. + */ extern uint8_t bcm2835_gpio_eds(uint8_t pin); - /// Sets the Event Detect Status register for a given pin to 1, - /// which has the effect of clearing the flag. Use this afer seeing - /// an Event Detect Status on the pin. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + /*! Same as bcm2835_gpio_eds() but checks if any of the pins specified in + the mask have detected a level or edge. + \param[in] mask Mask of pins to check. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) + \return Mask of pins HIGH if the event detect status for the given pin is true. + */ + extern uint32_t bcm2835_gpio_eds_multi(uint32_t mask); + + /*! Sets the Event Detect Status register for a given pin to 1, + which has the effect of clearing the flag. Use this afer seeing + an Event Detect Status on the pin. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + */ extern void bcm2835_gpio_set_eds(uint8_t pin); - /// Enable Rising Edge Detect Enable for the specified pin. - /// When a rising edge is detected, sets the appropriate pin in Event Detect Status. - /// The GPRENn registers use - /// synchronous edge detection. This means the input signal is sampled using the - /// system clock and then it is looking for a ?011? pattern on the sampled signal. This - /// has the effect of suppressing glitches. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + /*! Same as bcm2835_gpio_set_eds() but clears the flag for any pin which + is set in the mask. + \param[in] mask Mask of pins to clear. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) + */ + extern void bcm2835_gpio_set_eds_multi(uint32_t mask); + + /*! Enable Rising Edge Detect Enable for the specified pin. + When a rising edge is detected, sets the appropriate pin in Event Detect Status. + The GPRENn registers use + synchronous edge detection. This means the input signal is sampled using the + system clock and then it is looking for a ?011? pattern on the sampled signal. This + has the effect of suppressing glitches. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + */ extern void bcm2835_gpio_ren(uint8_t pin); - /// Disable Rising Edge Detect Enable for the specified pin. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + /*! Disable Rising Edge Detect Enable for the specified pin. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + */ extern void bcm2835_gpio_clr_ren(uint8_t pin); - /// Enable Falling Edge Detect Enable for the specified pin. - /// When a falling edge is detected, sets the appropriate pin in Event Detect Status. - /// The GPRENn registers use - /// synchronous edge detection. This means the input signal is sampled using the - /// system clock and then it is looking for a ?100? pattern on the sampled signal. This - /// has the effect of suppressing glitches. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + /*! Enable Falling Edge Detect Enable for the specified pin. + When a falling edge is detected, sets the appropriate pin in Event Detect Status. + The GPRENn registers use + synchronous edge detection. This means the input signal is sampled using the + system clock and then it is looking for a ?100? pattern on the sampled signal. This + has the effect of suppressing glitches. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + */ extern void bcm2835_gpio_fen(uint8_t pin); - /// Disable Falling Edge Detect Enable for the specified pin. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + /*! Disable Falling Edge Detect Enable for the specified pin. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + */ extern void bcm2835_gpio_clr_fen(uint8_t pin); - /// Enable High Detect Enable for the specified pin. - /// When a HIGH level is detected on the pin, sets the appropriate pin in Event Detect Status. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + /*! Enable High Detect Enable for the specified pin. + When a HIGH level is detected on the pin, sets the appropriate pin in Event Detect Status. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + */ extern void bcm2835_gpio_hen(uint8_t pin); - /// Disable High Detect Enable for the specified pin. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + /*! Disable High Detect Enable for the specified pin. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + */ extern void bcm2835_gpio_clr_hen(uint8_t pin); - /// Enable Low Detect Enable for the specified pin. - /// When a LOW level is detected on the pin, sets the appropriate pin in Event Detect Status. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + /*! Enable Low Detect Enable for the specified pin. + When a LOW level is detected on the pin, sets the appropriate pin in Event Detect Status. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + */ extern void bcm2835_gpio_len(uint8_t pin); - /// Disable Low Detect Enable for the specified pin. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + /*! Disable Low Detect Enable for the specified pin. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + */ extern void bcm2835_gpio_clr_len(uint8_t pin); - /// Enable Asynchronous Rising Edge Detect Enable for the specified pin. - /// When a rising edge is detected, sets the appropriate pin in Event Detect Status. - /// Asynchronous means the incoming signal is not sampled by the system clock. As such - /// rising edges of very short duration can be detected. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + /*! Enable Asynchronous Rising Edge Detect Enable for the specified pin. + When a rising edge is detected, sets the appropriate pin in Event Detect Status. + Asynchronous means the incoming signal is not sampled by the system clock. As such + rising edges of very short duration can be detected. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + */ extern void bcm2835_gpio_aren(uint8_t pin); - /// Disable Asynchronous Rising Edge Detect Enable for the specified pin. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + /*! Disable Asynchronous Rising Edge Detect Enable for the specified pin. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + */ extern void bcm2835_gpio_clr_aren(uint8_t pin); - /// Enable Asynchronous Falling Edge Detect Enable for the specified pin. - /// When a falling edge is detected, sets the appropriate pin in Event Detect Status. - /// Asynchronous means the incoming signal is not sampled by the system clock. As such - /// falling edges of very short duration can be detected. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + /*! Enable Asynchronous Falling Edge Detect Enable for the specified pin. + When a falling edge is detected, sets the appropriate pin in Event Detect Status. + Asynchronous means the incoming signal is not sampled by the system clock. As such + falling edges of very short duration can be detected. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + */ extern void bcm2835_gpio_afen(uint8_t pin); - /// Disable Asynchronous Falling Edge Detect Enable for the specified pin. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + /*! Disable Asynchronous Falling Edge Detect Enable for the specified pin. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + */ extern void bcm2835_gpio_clr_afen(uint8_t pin); - /// Sets the Pull-up/down register for the given pin. This is - /// used with bcm2835_gpio_pudclk() to set the Pull-up/down resistor for the given pin. - /// However, it is usually more convenient to use bcm2835_gpio_set_pud(). - /// \param[in] pud The desired Pull-up/down mode. One of BCM2835_GPIO_PUD_* from bcm2835PUDControl - /// \sa bcm2835_gpio_set_pud() + /*! Sets the Pull-up/down register for the given pin. This is + used with bcm2835_gpio_pudclk() to set the Pull-up/down resistor for the given pin. + However, it is usually more convenient to use bcm2835_gpio_set_pud(). + \param[in] pud The desired Pull-up/down mode. One of BCM2835_GPIO_PUD_* from bcm2835PUDControl + \sa bcm2835_gpio_set_pud() + */ extern void bcm2835_gpio_pud(uint8_t pud); - /// Clocks the Pull-up/down value set earlier by bcm2835_gpio_pud() into the pin. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - /// \param[in] on HIGH to clock the value from bcm2835_gpio_pud() into the pin. - /// LOW to remove the clock. - /// \sa bcm2835_gpio_set_pud() + /*! Clocks the Pull-up/down value set earlier by bcm2835_gpio_pud() into the pin. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + \param[in] on HIGH to clock the value from bcm2835_gpio_pud() into the pin. + LOW to remove the clock. + \sa bcm2835_gpio_set_pud() + */ extern void bcm2835_gpio_pudclk(uint8_t pin, uint8_t on); - /// Reads and returns the Pad Control for the given GPIO group. - /// \param[in] group The GPIO pad group number, one of BCM2835_PAD_GROUP_GPIO_* - /// \return Mask of bits from BCM2835_PAD_* from \ref bcm2835PadGroup + /*! Reads and returns the Pad Control for the given GPIO group. + \param[in] group The GPIO pad group number, one of BCM2835_PAD_GROUP_GPIO_* + \return Mask of bits from BCM2835_PAD_* from \ref bcm2835PadGroup + */ extern uint32_t bcm2835_gpio_pad(uint8_t group); - /// Sets the Pad Control for the given GPIO group. - /// \param[in] group The GPIO pad group number, one of BCM2835_PAD_GROUP_GPIO_* - /// \param[in] control Mask of bits from BCM2835_PAD_* from \ref bcm2835PadGroup. Note - /// that it is not necessary to include BCM2835_PAD_PASSWRD in the mask as this - /// is automatically included. + /*! Sets the Pad Control for the given GPIO group. + \param[in] group The GPIO pad group number, one of BCM2835_PAD_GROUP_GPIO_* + \param[in] control Mask of bits from BCM2835_PAD_* from \ref bcm2835PadGroup. Note + that it is not necessary to include BCM2835_PAD_PASSWRD in the mask as this + is automatically included. + */ extern void bcm2835_gpio_set_pad(uint8_t group, uint32_t control); - /// Delays for the specified number of milliseconds. - /// Uses nanosleep(), and therefore does not use CPU until the time is up. - /// However, you are at the mercy of nanosleep(). From the manual for nanosleep(): - /// If the interval specified in req is not an exact multiple of the granularity - /// underlying clock (see time(7)), then the interval will be - /// rounded up to the next multiple. Furthermore, after the sleep completes, - /// there may still be a delay before the CPU becomes free to once - /// again execute the calling thread. - /// \param[in] millis Delay in milliseconds + /*! Delays for the specified number of milliseconds. + Uses nanosleep(), and therefore does not use CPU until the time is up. + However, you are at the mercy of nanosleep(). From the manual for nanosleep(): + If the interval specified in req is not an exact multiple of the granularity + underlying clock (see time(7)), then the interval will be + rounded up to the next multiple. Furthermore, after the sleep completes, + there may still be a delay before the CPU becomes free to once + again execute the calling thread. + \param[in] millis Delay in milliseconds + */ extern void bcm2835_delay (unsigned int millis); - /// Delays for the specified number of microseconds. - /// Uses a combination of nanosleep() and a busy wait loop on the BCM2835 system timers, - /// However, you are at the mercy of nanosleep(). From the manual for nanosleep(): - /// If the interval specified in req is not an exact multiple of the granularity - /// underlying clock (see time(7)), then the interval will be - /// rounded up to the next multiple. Furthermore, after the sleep completes, - /// there may still be a delay before the CPU becomes free to once - /// again execute the calling thread. - /// For times less than about 450 microseconds, uses a busy wait on the System Timer. - /// It is reported that a delay of 0 microseconds on RaspberryPi will in fact - /// result in a delay of about 80 microseconds. Your mileage may vary. - /// \param[in] micros Delay in microseconds + /*! Delays for the specified number of microseconds. + Uses a combination of nanosleep() and a busy wait loop on the BCM2835 system timers, + However, you are at the mercy of nanosleep(). From the manual for nanosleep(): + If the interval specified in req is not an exact multiple of the granularity + underlying clock (see time(7)), then the interval will be + rounded up to the next multiple. Furthermore, after the sleep completes, + there may still be a delay before the CPU becomes free to once + again execute the calling thread. + For times less than about 450 microseconds, uses a busy wait on the System Timer. + It is reported that a delay of 0 microseconds on RaspberryPi will in fact + result in a delay of about 80 microseconds. Your mileage may vary. + \param[in] micros Delay in microseconds + */ extern void bcm2835_delayMicroseconds (uint64_t micros); - /// Sets the output state of the specified pin - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - /// \param[in] on HIGH sets the output to HIGH and LOW to LOW. + /*! Sets the output state of the specified pin + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + \param[in] on HIGH sets the output to HIGH and LOW to LOW. + */ extern void bcm2835_gpio_write(uint8_t pin, uint8_t on); - /// Sets any of the first 32 GPIO output pins specified in the mask to the state given by on - /// \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - /// \param[in] on HIGH sets the output to HIGH and LOW to LOW. + /*! Sets any of the first 32 GPIO output pins specified in the mask to the state given by on + \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) + \param[in] on HIGH sets the output to HIGH and LOW to LOW. + */ extern void bcm2835_gpio_write_multi(uint32_t mask, uint8_t on); - /// Sets the first 32 GPIO output pins specified in the mask to the value given by value - /// \param[in] value values required for each bit masked in by mask, eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - /// \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) + /*! Sets the first 32 GPIO output pins specified in the mask to the value given by value + \param[in] value values required for each bit masked in by mask, eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) + \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) + */ extern void bcm2835_gpio_write_mask(uint32_t value, uint32_t mask); - /// Sets the Pull-up/down mode for the specified pin. This is more convenient than - /// clocking the mode in with bcm2835_gpio_pud() and bcm2835_gpio_pudclk(). - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - /// \param[in] pud The desired Pull-up/down mode. One of BCM2835_GPIO_PUD_* from bcm2835PUDControl + /*! Sets the Pull-up/down mode for the specified pin. This is more convenient than + clocking the mode in with bcm2835_gpio_pud() and bcm2835_gpio_pudclk(). + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + \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 - /// 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. - /// 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(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. + /*! @} */ + + /*! \defgroup spi SPI access + 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. + You should call bcm2835_spi_end() when all SPI funcitons are complete to return the pins to + their default functions. + \sa bcm2835_spi_end() + \return 1 if successful, 0 otherwise (perhaps because you are not running as root) + */ + extern int 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 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_*, - /// see \ref bcm2835SPIBitOrder + /*! 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_*, + 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_*, - /// see \ref bcm2835SPIClockDivider + /*! 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*, - /// see \ref bcm2835SPIMode + /*! Sets the SPI data mode + Sets the clock polariy and phase + \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. - /// One of BCM2835_SPI_CS*, see \ref bcm2835SPIChipSelect + /*! 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. + 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) - /// 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 + /*! 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) + 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) - /// during the transfer. - /// 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() + /*! Transfers one byte to and from the currently selected SPI slave. + 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. + 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) - /// during the transfer. - /// 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[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() + /*! 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) + during the transfer. + 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[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() + */ extern void bcm2835_spi_transfernb(char* tbuf, char* rbuf, uint32_t len); - /// Transfers any number of bytes to and from the currently selected SPI slave - /// using bcm2835_spi_transfernb. - /// The returned data from the slave replaces the transmitted data in the buffer. - /// \param[in,out] buf Buffer of bytes to send. Received bytes will replace the contents - /// \param[in] len Number of bytes int eh buffer, and the number of bytes to send/received - /// \sa bcm2835_spi_transfer() + /*! Transfers any number of bytes to and from the currently selected SPI slave + using bcm2835_spi_transfernb. + The returned data from the slave replaces the transmitted data in the buffer. + \param[in,out] buf Buffer of bytes to send. Received bytes will replace the contents + \param[in] len Number of bytes int eh buffer, and the number of bytes to send/received + \sa bcm2835_spi_transfer() + */ extern void bcm2835_spi_transfern(char* buf, uint32_t len); - /// Transfers any number of bytes to the currently selected SPI slave. - /// Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) - /// during the transfer. - /// \param[in] buf Buffer of bytes to send. - /// \param[in] len Number of bytes in the tbuf buffer, and the number of bytes to send + /*! Transfers any number of bytes to the currently selected SPI slave. + Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) + during the transfer. + \param[in] buf Buffer of bytes to send. + \param[in] len Number of bytes in the tbuf buffer, and the number of bytes to send + */ extern void bcm2835_spi_writenb(char* buf, uint32_t len); - /// @} - - /// \defgroup i2c I2C access - /// These functions let you use I2C (The Broadcom Serial Control bus with the Philips - /// I2C bus/interface version 2.1 January 2000.) to interface with an external I2C device. - /// @{ - - /// Start I2C operations. - /// Forces RPi I2C pins P1-03 (SDA) and P1-05 (SCL) - /// to alternate function ALT0, which enables those pins for I2C interface. - /// You should call bcm2835_i2c_end() when all I2C functions are complete to return the pins to - /// their default functions - /// \sa bcm2835_i2c_end() - extern void bcm2835_i2c_begin(void); - - /// End I2C operations. - /// I2C pins P1-03 (SDA) and P1-05 (SCL) - /// are returned to their default INPUT behaviour. + /*! @} */ + + /*! \defgroup i2c I2C access + These functions let you use I2C (The Broadcom Serial Control bus with the Philips + I2C bus/interface version 2.1 January 2000.) to interface with an external I2C device. + @{ + */ + + /*! Start I2C operations. + Forces RPi I2C pins P1-03 (SDA) and P1-05 (SCL) + to alternate function ALT0, which enables those pins for I2C interface. + You should call bcm2835_i2c_end() when all I2C functions are complete to return the pins to + their default functions + \return 1 if successful, 0 otherwise (perhaps because you are not running as root) + \sa bcm2835_i2c_end() + */ + extern int bcm2835_i2c_begin(void); + + /*! End I2C operations. + I2C pins P1-03 (SDA) and P1-05 (SCL) + are returned to their default INPUT behaviour. + */ extern void bcm2835_i2c_end(void); - /// Sets the I2C slave address. - /// \param[in] addr The I2C slave address. + /*! Sets the I2C slave address. + \param[in] addr The I2C slave address. + */ extern void bcm2835_i2c_setSlaveAddress(uint8_t addr); - /// Sets the I2C clock divider and therefore the I2C clock speed. - /// \param[in] divider The desired I2C clock divider, one of BCM2835_I2C_CLOCK_DIVIDER_*, - /// see \ref bcm2835I2CClockDivider + /*! Sets the I2C clock divider and therefore the I2C clock speed. + \param[in] divider The desired I2C clock divider, one of BCM2835_I2C_CLOCK_DIVIDER_*, + see \ref bcm2835I2CClockDivider + */ extern void bcm2835_i2c_setClockDivider(uint16_t divider); - /// Sets the I2C clock divider by converting the baudrate parameter to - /// the equivalent I2C clock divider. ( see \sa bcm2835_i2c_setClockDivider) - /// For the I2C standard 100khz you would set baudrate to 100000 - /// The use of baudrate corresponds to its use in the I2C kernel device - /// driver. (Of course, bcm2835 has nothing to do with the kernel driver) + /*! Sets the I2C clock divider by converting the baudrate parameter to + the equivalent I2C clock divider. ( see \sa bcm2835_i2c_setClockDivider) + For the I2C standard 100khz you would set baudrate to 100000 + The use of baudrate corresponds to its use in the I2C kernel device + driver. (Of course, bcm2835 has nothing to do with the kernel driver) + */ extern void bcm2835_i2c_set_baudrate(uint32_t baudrate); - /// Transfers any number of bytes to the currently selected I2C slave. - /// (as previously set by \sa bcm2835_i2c_setSlaveAddress) - /// \param[in] buf Buffer of bytes to send. - /// \param[in] len Number of bytes in the buf buffer, and the number of bytes to send. - /// \return reason see \ref bcm2835I2CReasonCodes + /*! Transfers any number of bytes to the currently selected I2C slave. + (as previously set by \sa bcm2835_i2c_setSlaveAddress) + \param[in] buf Buffer of bytes to send. + \param[in] len Number of bytes in the buf buffer, and the number of bytes to send. + \return reason see \ref bcm2835I2CReasonCodes + */ extern uint8_t bcm2835_i2c_write(const char * buf, uint32_t len); - /// Transfers any number of bytes from the currently selected I2C slave. - /// (as previously set by \sa bcm2835_i2c_setSlaveAddress) - /// \param[in] buf Buffer of bytes to receive. - /// \param[in] len Number of bytes in the buf buffer, and the number of bytes to received. - /// \return reason see \ref bcm2835I2CReasonCodes + /*! Transfers any number of bytes from the currently selected I2C slave. + (as previously set by \sa bcm2835_i2c_setSlaveAddress) + \param[in] buf Buffer of bytes to receive. + \param[in] len Number of bytes in the buf buffer, and the number of bytes to received. + \return reason see \ref bcm2835I2CReasonCodes + */ extern uint8_t bcm2835_i2c_read(char* buf, uint32_t len); - /// Allows reading from I2C slaves that require a repeated start (without any prior stop) - /// to read after the required slave register has been set. For example, the popular - /// MPL3115A2 pressure and temperature sensor. Note that your device must support or - /// require this mode. If your device does not require this mode then the standard - /// combined: - /// \sa bcm2835_i2c_write - /// \sa bcm2835_i2c_read - /// are a better choice. - /// Will read from the slave previously set by \sa bcm2835_i2c_setSlaveAddress - /// \param[in] regaddr Buffer containing the slave register you wish to read from. - /// \param[in] buf Buffer of bytes to receive. - /// \param[in] len Number of bytes in the buf buffer, and the number of bytes to received. - /// \return reason see \ref bcm2835I2CReasonCodes + /*! Allows reading from I2C slaves that require a repeated start (without any prior stop) + to read after the required slave register has been set. For example, the popular + MPL3115A2 pressure and temperature sensor. Note that your device must support or + require this mode. If your device does not require this mode then the standard + combined: + \sa bcm2835_i2c_write + \sa bcm2835_i2c_read + are a better choice. + Will read from the slave previously set by \sa bcm2835_i2c_setSlaveAddress + \param[in] regaddr Buffer containing the slave register you wish to read from. + \param[in] buf Buffer of bytes to receive. + \param[in] len Number of bytes in the buf buffer, and the number of bytes to received. + \return reason see \ref bcm2835I2CReasonCodes + */ extern uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len); - /// Allows sending an arbitrary number of bytes to I2C slaves before issuing a repeated - /// start (with no prior stop) and reading a response. - /// Necessary for devices that require such behavior, such as the MLX90620. - /// Will write to and read from the slave previously set by \sa bcm2835_i2c_setSlaveAddress - /// \param[in] cmds Buffer containing the bytes to send before the repeated start condition. - /// \param[in] cmds_len Number of bytes to send from cmds buffer - /// \param[in] buf Buffer of bytes to receive. - /// \param[in] buf_len Number of bytes to receive in the buf buffer. - /// \return reason see \ref bcm2835I2CReasonCodes + /*! Allows sending an arbitrary number of bytes to I2C slaves before issuing a repeated + start (with no prior stop) and reading a response. + Necessary for devices that require such behavior, such as the MLX90620. + Will write to and read from the slave previously set by \sa bcm2835_i2c_setSlaveAddress + \param[in] cmds Buffer containing the bytes to send before the repeated start condition. + \param[in] cmds_len Number of bytes to send from cmds buffer + \param[in] buf Buffer of bytes to receive. + \param[in] buf_len Number of bytes to receive in the buf buffer. + \return reason see \ref bcm2835I2CReasonCodes + */ extern uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint32_t buf_len); - /// @} + /*! @} */ - /// \defgroup st System Timer access - /// Allows access to and delays using the System Timer Counter. - /// @{ + /*! \defgroup st System Timer access + Allows access to and delays using the System Timer Counter. + @{ + */ - /// Read the System Timer Counter register. - /// \return the value read from the System Timer Counter Lower 32 bits register + /*! Read the System Timer Counter register. + \return the value read from the System Timer Counter Lower 32 bits register + */ extern uint64_t bcm2835_st_read(void); - /// Delays for the specified number of microseconds with offset. - /// \param[in] offset_micros Offset in microseconds - /// \param[in] micros Delay in microseconds + /*! Delays for the specified number of microseconds with offset. + \param[in] offset_micros Offset in microseconds + \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 - /// can be connected to one of these 2 channels, allowing PWM control of GPIO pins. - /// You have to set the desired pin into a particular Alt Fun to PWM output. See the PWM - /// documentation on the Main Page. - /// @{ - - /// 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 + /*! @} */ + + /*! \defgroup pwm Pulse Width Modulation + Allows control of 2 independent PWM channels. A limited subset of GPIO pins + can be connected to one of these 2 channels, allowing PWM control of GPIO pins. + You have to set the desired pin into a particular Alt Fun to PWM output. See the PWM + documentation on the Main Page. + @{ + */ + + /*! 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. - /// \param[in] markspace Set true if you want Mark-Space mode. 0 for Balanced mode. - /// \param[in] enabled Set true to enable this channel and produce PWM pulses. + /*! 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. + \param[in] markspace Set true if you want Mark-Space mode. 0 for Balanced mode. + \param[in] enabled Set true to enable this channel and produce PWM pulses. + */ extern void bcm2835_pwm_set_mode(uint8_t channel, uint8_t markspace, uint8_t enabled); - /// Sets the maximum range of the PWM output. - /// The data value can vary between 0 and this range to control PWM output - /// \param[in] channel The PWM channel. 0 or 1. - /// \param[in] range The maximum value permitted for DATA. + /*! Sets the maximum range of the PWM output. + The data value can vary between 0 and this range to control PWM output + \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, - /// 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. - /// Can vary from 0 to 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. + Can vary from 0 to RANGE. + */ extern void bcm2835_pwm_set_data(uint8_t channel, uint32_t data); - /// @} + /*! @} */ #ifdef __cplusplus } #endif -#endif // BCM2835_H +#endif /* BCM2835_H */ -/// @example blink.c -/// Blinks RPi GPIO pin 11 on and off +/*! @example blink.c + Blinks RPi GPIO pin 11 on and off +*/ -/// @example input.c -/// Reads the state of an RPi input pin +/*! @example input.c + Reads the state of an RPi input pin +*/ -/// @example event.c -/// Shows how to use event detection on an input pin +/*! @example event.c + Shows how to use event detection on an input pin +*/ -/// @example spi.c -/// Shows how to use SPI interface to transfer a byte to and from an SPI device +/*! @example spi.c + Shows how to use SPI interface to transfer a byte to and from an SPI device +*/ -/// @example spin.c -/// Shows how to use SPI interface to transfer a number of bytes to and from an SPI device +/*! @example spin.c + Shows how to use SPI interface to transfer a number of bytes to and from an SPI device +*/ -/// @example pwm.c -/// Shows how to use PWM to control GPIO pins +/*! @example pwm.c + Shows how to use PWM to control GPIO pins +*/ -/// @example i2c.c -/// Command line utility for executing i2c commands with the -/// Broadcom bcm2835. Contributed by Shahrooz Shahparnia. +/*! @example i2c.c +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 -/// Broadcom bcm2835. Contributed by Shahrooz Shahparnia. +/*! example gpio.c + Command line utility for executing gpio commands with the + Broadcom bcm2835. Contributed by Shahrooz Shahparnia. +*/ diff --git a/src/test.c b/src/test.c index c9a69ed..af91133 100644 --- a/src/test.c +++ b/src/test.c @@ -5,7 +5,7 @@ // // Author: Mike McCauley // Copyright (C) 2011-2013 Mike McCauley -// $Id: test.c,v 1.4 2013/03/17 06:08:29 mikem Exp $ +// $Id: test.c,v 1.5 2015/03/28 05:27:32 mikem Exp $ #include #include diff --git a/test-driver b/test-driver new file mode 100755 index 0000000..32bf39e --- /dev/null +++ b/test-driver @@ -0,0 +1,127 @@ +#! /bin/sh +# test-driver - basic testsuite driver script. + +scriptversion=2012-06-27.10; # UTC + +# Copyright (C) 2011-2013 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +# Make unconditional expansion of undefined variables an error. This +# helps a lot in preventing typo-related bugs. +set -u + +usage_error () +{ + echo "$0: $*" >&2 + print_usage >&2 + exit 2 +} + +print_usage () +{ + cat <$log_file 2>&1 +estatus=$? +if test $enable_hard_errors = no && test $estatus -eq 99; then + estatus=1 +fi + +case $estatus:$expect_failure in + 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; + 0:*) col=$grn res=PASS recheck=no gcopy=no;; + 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; + 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; + *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; + *:*) col=$red res=FAIL recheck=yes gcopy=yes;; +esac + +# Report outcome to console. +echo "${col}${res}${std}: $test_name" + +# Register the test result, and other relevant metadata. +echo ":test-result: $res" > $trs_file +echo ":global-test-result: $res" >> $trs_file +echo ":recheck: $recheck" >> $trs_file +echo ":copy-in-global-log: $gcopy" >> $trs_file + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: From 9bf8b676e37df1acfcd47b91b6e08e697d9d0fed Mon Sep 17 00:00:00 2001 From: Romeo-Golf Date: Mon, 2 Jan 2017 23:45:33 +0000 Subject: [PATCH 2/2] Merge upstream 1.51 from http://www.airspayce.com/mikem/bcm2835/bcm2835-1.51.tar.gz --- configure | 20 +- configure.ac | 2 +- examples/pwm/pwm.c | 17 +- missing | 461 +++++++++++++++------------------------------ src/bcm2835.c | 15 +- src/bcm2835.h | 63 ++++--- 6 files changed, 226 insertions(+), 352 deletions(-) diff --git a/configure b/configure index 10471de..f58a2ee 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for bcm2835 1.50. +# Generated by GNU Autoconf 2.69 for bcm2835 1.51. # # Report bugs to . # @@ -579,8 +579,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='bcm2835' PACKAGE_TARNAME='bcm2835' -PACKAGE_VERSION='1.50' -PACKAGE_STRING='bcm2835 1.50' +PACKAGE_VERSION='1.51' +PACKAGE_STRING='bcm2835 1.51' PACKAGE_BUGREPORT='mikem@airspayce.com' PACKAGE_URL='' @@ -1228,7 +1228,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures bcm2835 1.50 to adapt to many kinds of systems. +\`configure' configures bcm2835 1.51 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1294,7 +1294,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of bcm2835 1.50:";; + short | recursive ) echo "Configuration of bcm2835 1.51:";; esac cat <<\_ACEOF @@ -1384,7 +1384,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -bcm2835 configure 1.50 +bcm2835 configure 1.51 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1485,7 +1485,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by bcm2835 $as_me 1.50, which was +It was created by bcm2835 $as_me 1.51, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2351,7 +2351,7 @@ fi # Define the identity of the package. PACKAGE='bcm2835' - VERSION='1.50' + VERSION='1.51' cat >>confdefs.h <<_ACEOF @@ -4785,7 +4785,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by bcm2835 $as_me 1.50, which was +This file was extended by bcm2835 $as_me 1.51, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -4851,7 +4851,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -bcm2835 config.status 1.50 +bcm2835 config.status 1.51 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 206a305..95871d2 100644 --- a/configure.ac +++ b/configure.ac @@ -6,7 +6,7 @@ dnl (C) 2012 Mike McCauley (mikem@airspayce.com) dnl Dont forget to update BCM2835_VERSION and .tar.gz in bcm2835.h dnl and the zip file. -AC_INIT([bcm2835], [1.50], [mikem@airspayce.com]) +AC_INIT([bcm2835], [1.51], [mikem@airspayce.com]) AM_CONFIG_HEADER(config.h) AM_INIT_AUTOMAKE() diff --git a/examples/pwm/pwm.c b/examples/pwm/pwm.c index 8311884..3685062 100644 --- a/examples/pwm/pwm.c +++ b/examples/pwm/pwm.c @@ -12,6 +12,8 @@ // gcc -o pwm -I ../../src ../../src/bcm2835.c pwm.c // sudo ./pwm // +// Connect an LED between GPIO18 (pin 12) and GND to observe the LED changing in brightness +// // Author: Mike McCauley // Copyright (C) 2013 Mike McCauley // $Id: RF22.h,v 1.21 2012/05/30 01:51:25 mikem Exp $ @@ -45,18 +47,19 @@ int main(int argc, char **argv) bcm2835_pwm_set_range(PWM_CHANNEL, RANGE); // Vary the PWM m/s ratio between 1/RANGE and (RANGE-1)/RANGE - int direction = 1; + // over the course of a a few seconds + int direction = 1; // 1 is increase, -1 is decrease int data = 1; while (1) - { + { if (data == 1) - direction = 1; + direction = 1; // Switch to increasing else if (data == RANGE-1) - direction = -1; + direction = -1; // Switch to decreasing data += direction; - bcm2835_pwm_set_data(PWM_CHANNEL, data); - bcm2835_delay(50); - } + bcm2835_pwm_set_data(PWM_CHANNEL, data); + bcm2835_delay(1); + } bcm2835_close(); return 0; diff --git a/missing b/missing index 28055d2..cdea514 100755 --- a/missing +++ b/missing @@ -1,11 +1,10 @@ #! /bin/sh -# Common stub for a few missing GNU programs while installing. +# Common wrapper for a few potentially missing GNU programs. -scriptversion=2009-04-28.21; # UTC +scriptversion=2012-06-26.16; # UTC -# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006, -# 2008, 2009 Free Software Foundation, Inc. -# Originally by Fran,cois Pinard , 1996. +# Copyright (C) 1996-2013 Free Software Foundation, Inc. +# Originally written by Fran,cois Pinard , 1996. # 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 @@ -26,69 +25,40 @@ scriptversion=2009-04-28.21; # UTC # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then - echo 1>&2 "Try \`$0 --help' for more information" + echo 1>&2 "Try '$0 --help' for more information" exit 1 fi -run=: -sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' -sed_minuso='s/.* -o \([^ ]*\).*/\1/p' - -# In the cases where this matters, `missing' is being run in the -# srcdir already. -if test -f configure.ac; then - configure_ac=configure.ac -else - configure_ac=configure.in -fi +case $1 in -msg="missing on your system" + --is-lightweight) + # Used by our autoconf macros to check whether the available missing + # script is modern enough. + exit 0 + ;; -case $1 in ---run) - # Try to run requested program, and just exit if it succeeds. - run= - shift - "$@" && exit 0 - # Exit code 63 means version mismatch. This often happens - # when the user try to use an ancient version of a tool on - # a file that requires a minimum version. In this case we - # we should proceed has if the program had been absent, or - # if --run hadn't been passed. - if test $? = 63; then - run=: - msg="probably too old" - fi - ;; + --run) + # Back-compat with the calling convention used by older automake. + shift + ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... -Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an -error status if there is no known handling for PROGRAM. +Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due +to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit - --run try to run the given command, and emulate it if it fails Supported PROGRAM values: - aclocal touch file \`aclocal.m4' - autoconf touch file \`configure' - autoheader touch file \`config.h.in' - autom4te touch the output file, or create a stub one - automake touch all \`Makefile.in' files - bison create \`y.tab.[ch]', if possible, from existing .[ch] - flex create \`lex.yy.c', if possible, from existing .c - help2man touch the output file - lex create \`lex.yy.c', if possible, from existing .c - makeinfo touch the output file - tar try tar, gnutar, gtar, then tar without non-portable flags - yacc create \`y.tab.[ch]', if possible, from existing .[ch] + aclocal autoconf autoheader autom4te automake makeinfo + bison yacc flex lex help2man -Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and -\`g' are ignored when checking the name. +Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and +'g' are ignored when checking the name. Send bug reports to ." exit $? @@ -100,272 +70,141 @@ Send bug reports to ." ;; -*) - echo 1>&2 "$0: Unknown \`$1' option" - echo 1>&2 "Try \`$0 --help' for more information" + echo 1>&2 "$0: unknown '$1' option" + echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac -# normalize program name to check for. -program=`echo "$1" | sed ' - s/^gnu-//; t - s/^gnu//; t - s/^g//; t'` - -# Now exit if we have it, but it failed. Also exit now if we -# don't have it and --version was passed (most likely to detect -# the program). This is about non-GNU programs, so use $1 not -# $program. -case $1 in - lex*|yacc*) - # Not GNU programs, they don't have --version. - ;; - - tar*) - if test -n "$run"; then - echo 1>&2 "ERROR: \`tar' requires --run" - exit 1 - elif test "x$2" = "x--version" || test "x$2" = "x--help"; then - exit 1 - fi - ;; - - *) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - elif test "x$2" = "x--version" || test "x$2" = "x--help"; then - # Could not run --version or --help. This is probably someone - # running `$TOOL --version' or `$TOOL --help' to check whether - # $TOOL exists and not knowing $TOOL uses missing. - exit 1 - fi - ;; -esac - -# If it does not exist, or fails to run (possibly an outdated version), -# try to emulate it. -case $program in - aclocal*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`acinclude.m4' or \`${configure_ac}'. You might want - to install the \`Automake' and \`Perl' packages. Grab them from - any GNU archive site." - touch aclocal.m4 - ;; - - autoconf*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`${configure_ac}'. You might want to install the - \`Autoconf' and \`GNU m4' packages. Grab them from any GNU - archive site." - touch configure - ;; - - autoheader*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`acconfig.h' or \`${configure_ac}'. You might want - to install the \`Autoconf' and \`GNU m4' packages. Grab them - from any GNU archive site." - files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` - test -z "$files" && files="config.h" - touch_files= - for f in $files; do - case $f in - *:*) touch_files="$touch_files "`echo "$f" | - sed -e 's/^[^:]*://' -e 's/:.*//'`;; - *) touch_files="$touch_files $f.in";; - esac - done - touch $touch_files - ;; - - automake*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. - You might want to install the \`Automake' and \`Perl' packages. - Grab them from any GNU archive site." - find . -type f -name Makefile.am -print | - sed 's/\.am$/.in/' | - while read f; do touch "$f"; done - ;; - - autom4te*) - echo 1>&2 "\ -WARNING: \`$1' is needed, but is $msg. - You might have modified some files without having the - proper tools for further handling them. - You can get \`$1' as part of \`Autoconf' from any GNU - archive site." - - file=`echo "$*" | sed -n "$sed_output"` - test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` - if test -f "$file"; then - touch $file - else - test -z "$file" || exec >$file - echo "#! /bin/sh" - echo "# Created by GNU Automake missing as a replacement of" - echo "# $ $@" - echo "exit 0" - chmod +x $file - exit 1 - fi - ;; - - bison*|yacc*) - echo 1>&2 "\ -WARNING: \`$1' $msg. You should only need it if - you modified a \`.y' file. You may need the \`Bison' package - in order for those modifications to take effect. You can get - \`Bison' from any GNU archive site." - rm -f y.tab.c y.tab.h - if test $# -ne 1; then - eval LASTARG="\${$#}" - case $LASTARG in - *.y) - SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` - if test -f "$SRCFILE"; then - cp "$SRCFILE" y.tab.c - fi - SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` - if test -f "$SRCFILE"; then - cp "$SRCFILE" y.tab.h - fi - ;; - esac - fi - if test ! -f y.tab.h; then - echo >y.tab.h - fi - if test ! -f y.tab.c; then - echo 'main() { return 0; }' >y.tab.c - fi - ;; - - lex*|flex*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified a \`.l' file. You may need the \`Flex' package - in order for those modifications to take effect. You can get - \`Flex' from any GNU archive site." - rm -f lex.yy.c - if test $# -ne 1; then - eval LASTARG="\${$#}" - case $LASTARG in - *.l) - SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` - if test -f "$SRCFILE"; then - cp "$SRCFILE" lex.yy.c - fi - ;; - esac - fi - if test ! -f lex.yy.c; then - echo 'main() { return 0; }' >lex.yy.c - fi - ;; - - help2man*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified a dependency of a manual page. You may need the - \`Help2man' package in order for those modifications to take - effect. You can get \`Help2man' from any GNU archive site." - - file=`echo "$*" | sed -n "$sed_output"` - test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` - if test -f "$file"; then - touch $file - else - test -z "$file" || exec >$file - echo ".ab help2man is required to generate this page" - exit $? - fi - ;; - - makeinfo*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified a \`.texi' or \`.texinfo' file, or any other file - indirectly affecting the aspect of the manual. The spurious - call might also be the consequence of using a buggy \`make' (AIX, - DU, IRIX). You might want to install the \`Texinfo' package or - the \`GNU make' package. Grab either from any GNU archive site." - # The file to touch is that specified with -o ... - file=`echo "$*" | sed -n "$sed_output"` - test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` - if test -z "$file"; then - # ... or it is the one specified with @setfilename ... - infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` - file=`sed -n ' - /^@setfilename/{ - s/.* \([^ ]*\) *$/\1/ - p - q - }' $infile` - # ... or it is derived from the source name (dir/f.texi becomes f.info) - test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info - fi - # If the file does not exist, the user really needs makeinfo; - # let's fail without touching anything. - test -f $file || exit 1 - touch $file - ;; - - tar*) - shift - - # We have already tried tar in the generic part. - # Look for gnutar/gtar before invocation to avoid ugly error - # messages. - if (gnutar --version > /dev/null 2>&1); then - gnutar "$@" && exit 0 - fi - if (gtar --version > /dev/null 2>&1); then - gtar "$@" && exit 0 - fi - firstarg="$1" - if shift; then - case $firstarg in - *o*) - firstarg=`echo "$firstarg" | sed s/o//` - tar "$firstarg" "$@" && exit 0 - ;; - esac - case $firstarg in - *h*) - firstarg=`echo "$firstarg" | sed s/h//` - tar "$firstarg" "$@" && exit 0 - ;; - esac - fi - - echo 1>&2 "\ -WARNING: I can't seem to be able to run \`tar' with the given arguments. - You may want to install GNU tar or Free paxutils, or check the - command line arguments." - exit 1 - ;; - - *) - echo 1>&2 "\ -WARNING: \`$1' is needed, and is $msg. - You might have modified some files without having the - proper tools for further handling them. Check the \`README' file, - it often tells you about the needed prerequisites for installing - this package. You may also peek at any GNU archive site, in case - some other package would contain this missing \`$1' program." - exit 1 - ;; -esac +# Run the given program, remember its exit status. +"$@"; st=$? + +# If it succeeded, we are done. +test $st -eq 0 && exit 0 + +# Also exit now if we it failed (or wasn't found), and '--version' was +# passed; such an option is passed most likely to detect whether the +# program is present and works. +case $2 in --version|--help) exit $st;; esac + +# Exit code 63 means version mismatch. This often happens when the user +# tries to use an ancient version of a tool on a file that requires a +# minimum version. +if test $st -eq 63; then + msg="probably too old" +elif test $st -eq 127; then + # Program was missing. + msg="missing on your system" +else + # Program was found and executed, but failed. Give up. + exit $st +fi -exit 0 +perl_URL=http://www.perl.org/ +flex_URL=http://flex.sourceforge.net/ +gnu_software_URL=http://www.gnu.org/software + +program_details () +{ + case $1 in + aclocal|automake) + echo "The '$1' program is part of the GNU Automake package:" + echo "<$gnu_software_URL/automake>" + echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/autoconf>" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + autoconf|autom4te|autoheader) + echo "The '$1' program is part of the GNU Autoconf package:" + echo "<$gnu_software_URL/autoconf/>" + echo "It also requires GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + esac +} + +give_advice () +{ + # Normalize program name to check for. + normalized_program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + + printf '%s\n' "'$1' is $msg." + + configure_deps="'configure.ac' or m4 files included by 'configure.ac'" + case $normalized_program in + autoconf*) + echo "You should only need it if you modified 'configure.ac'," + echo "or m4 files included by it." + program_details 'autoconf' + ;; + autoheader*) + echo "You should only need it if you modified 'acconfig.h' or" + echo "$configure_deps." + program_details 'autoheader' + ;; + automake*) + echo "You should only need it if you modified 'Makefile.am' or" + echo "$configure_deps." + program_details 'automake' + ;; + aclocal*) + echo "You should only need it if you modified 'acinclude.m4' or" + echo "$configure_deps." + program_details 'aclocal' + ;; + autom4te*) + echo "You might have modified some maintainer files that require" + echo "the 'automa4te' program to be rebuilt." + program_details 'autom4te' + ;; + bison*|yacc*) + echo "You should only need it if you modified a '.y' file." + echo "You may want to install the GNU Bison package:" + echo "<$gnu_software_URL/bison/>" + ;; + lex*|flex*) + echo "You should only need it if you modified a '.l' file." + echo "You may want to install the Fast Lexical Analyzer package:" + echo "<$flex_URL>" + ;; + help2man*) + echo "You should only need it if you modified a dependency" \ + "of a man page." + echo "You may want to install the GNU Help2man package:" + echo "<$gnu_software_URL/help2man/>" + ;; + makeinfo*) + echo "You should only need it if you modified a '.texi' file, or" + echo "any other file indirectly affecting the aspect of the manual." + echo "You might want to install the Texinfo package:" + echo "<$gnu_software_URL/texinfo/>" + echo "The spurious makeinfo call might also be the consequence of" + echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" + echo "want to install GNU make:" + echo "<$gnu_software_URL/make/>" + ;; + *) + echo "You might have modified some files without having the proper" + echo "tools for further handling them. Check the 'README' file, it" + echo "often tells you about the needed prerequisites for installing" + echo "this package. You may also peek at any GNU archive site, in" + echo "case some other package contains this missing '$1' program." + ;; + esac +} + +give_advice "$1" | sed -e '1s/^/WARNING: /' \ + -e '2,$s/^/ /' >&2 + +# Propagate the correct exit status (expected to be 127 for a program +# not found, 63 for a program that failed due to version mismatch). +exit $st # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) diff --git a/src/bcm2835.c b/src/bcm2835.c index c3dc5c7..9ca59c0 100644 --- a/src/bcm2835.c +++ b/src/bcm2835.c @@ -455,7 +455,16 @@ void bcm2835_delayMicroseconds(uint64_t micros) // long waits and use a busy wait on the System Timer for the rest. */ start = bcm2835_st_read(); - + + /* Not allowed to access timer registers (result is not as precise)*/ + if (start==0) + { + t1.tv_sec = 0; + t1.tv_nsec = 1000 * (long)(micros); + nanosleep(&t1, NULL); + return; + } + if (micros > 450) { t1.tv_sec = 0; @@ -1154,6 +1163,10 @@ uint64_t bcm2835_st_read(void) volatile uint32_t* paddr; uint32_t hi, lo; uint64_t st; + + if (bcm2835_st==MAP_FAILED) + return 0; + paddr = bcm2835_st + BCM2835_ST_CHI/4; hi = bcm2835_peri_read(paddr); diff --git a/src/bcm2835.h b/src/bcm2835.h index d92a8a2..770508f 100644 --- a/src/bcm2835.h +++ b/src/bcm2835.h @@ -10,7 +10,7 @@ /*! \mainpage C library for Broadcom BCM 2835 as used in Raspberry Pi This is a C library for Raspberry Pi (RPi). It provides access to - GPIO and other IO functions on the Broadcom BCM 2835 chip, + GPIO and other IO functions on the Broadcom BCM 2835 chip, as used in the RaspberryPi, allowing access to the GPIO pins on the 26 pin IDE plug on the RPi board so you can control and interface with various external devices. @@ -159,6 +159,12 @@ - P1-23 (CLK) - P1-24 (CE0) - P1-26 (CE1) + + Although it is possible to select high speeds for the SPI interface, up to 125MHz (see bcm2835_spi_setClockDivider()) + you should not expect to actually achieve those sorts of speeds with the RPi wiring. Our tests on RPi 2 show that the + SPI CLK line when unloaded has a resonant frequency of about 40MHz, and when loaded, the MOSI and MISO lines + ring at an even lower frequency. Measurements show that SPI waveforms are very poor and unusable at 62 and 125MHz. + Dont expect any speed faster than 31MHz to work reliably. \par I2C Pins @@ -448,6 +454,10 @@ (which prevents access to the SPI and I2C peripherals, amongst others). Testing on Raspbian Jessie. + \version 1.51 2016-11-03 + Added documentation about SPI cock divider and resulting SPI speeds on RPi3. + Fixed a problem where seg fault could occur in bcm2835_delayMicroseconds() if not running as root. Patch from Pok. + \author Mike McCauley (mikem@airspayce.com) DO NOT CONTACT THE AUTHOR DIRECTLY: USE THE LISTS */ @@ -737,7 +747,7 @@ typedef enum RPI_V2_GPIO_P1_31 = 6, /*!< Version 2, Pin P1-31 */ RPI_V2_GPIO_P1_32 = 12, /*!< Version 2, Pin P1-32 */ RPI_V2_GPIO_P1_33 = 13, /*!< Version 2, Pin P1-33 */ - RPI_V2_GPIO_P1_35 = 19, /*!< Version 2, Pin P1-35 */ + RPI_V2_GPIO_P1_35 = 19, /*!< Version 2, Pin P1-35, can be PWM channel 1 in ALT FUN 5 */ RPI_V2_GPIO_P1_36 = 16, /*!< Version 2, Pin P1-36 */ RPI_V2_GPIO_P1_37 = 26, /*!< Version 2, Pin P1-37 */ RPI_V2_GPIO_P1_38 = 20, /*!< Version 2, Pin P1-38 */ @@ -771,7 +781,7 @@ typedef enum RPI_BPLUS_GPIO_J8_31 = 6, /*!< B+, Pin J8-31, */ RPI_BPLUS_GPIO_J8_32 = 12, /*!< B+, Pin J8-32, */ RPI_BPLUS_GPIO_J8_33 = 13, /*!< B+, Pin J8-33, */ - RPI_BPLUS_GPIO_J8_35 = 19, /*!< B+, Pin J8-35, */ + RPI_BPLUS_GPIO_J8_35 = 19, /*!< B+, Pin J8-35, can be PWM channel 1 in ALT FUN 5 */ RPI_BPLUS_GPIO_J8_36 = 16, /*!< B+, Pin J8-36, */ RPI_BPLUS_GPIO_J8_37 = 26, /*!< B+, Pin J8-37, */ RPI_BPLUS_GPIO_J8_38 = 20, /*!< B+, Pin J8-38, */ @@ -851,29 +861,36 @@ typedef enum /*! \brief bcm2835SPIClockDivider Specifies the divider used to generate the SPI clock from the system clock. Figures below give the divider, clock period and clock frequency. - Clock divided is based on nominal base clock rate of 250MHz + Clock divided is based on nominal core clock rate of 250MHz on RPi1 and RPi2, and 400MHz on RPi3. It is reported that (contrary to the documentation) any even divider may used. - The frequencies shown for each divider have been confirmed by measurement. + The frequencies shown for each divider have been confirmed by measurement on RPi1 and RPi2. + The system clock frequency on RPi3 is different, so the frequency you get from a given divider will be different. + See comments in 'SPI Pins' for information about reliable SPI speeds. + Note: it is possible to change the core clock rate of the RPi 3 back to 250MHz, by putting + \code + core_freq=250 + \endcode + in the config.txt */ typedef enum { - BCM2835_SPI_CLOCK_DIVIDER_65536 = 0, /*!< 65536 = 262.144us = 3.814697260kHz */ - BCM2835_SPI_CLOCK_DIVIDER_32768 = 32768, /*!< 32768 = 131.072us = 7.629394531kHz */ - BCM2835_SPI_CLOCK_DIVIDER_16384 = 16384, /*!< 16384 = 65.536us = 15.25878906kHz */ - BCM2835_SPI_CLOCK_DIVIDER_8192 = 8192, /*!< 8192 = 32.768us = 30/51757813kHz */ - BCM2835_SPI_CLOCK_DIVIDER_4096 = 4096, /*!< 4096 = 16.384us = 61.03515625kHz */ - BCM2835_SPI_CLOCK_DIVIDER_2048 = 2048, /*!< 2048 = 8.192us = 122.0703125kHz */ - BCM2835_SPI_CLOCK_DIVIDER_1024 = 1024, /*!< 1024 = 4.096us = 244.140625kHz */ - BCM2835_SPI_CLOCK_DIVIDER_512 = 512, /*!< 512 = 2.048us = 488.28125kHz */ - BCM2835_SPI_CLOCK_DIVIDER_256 = 256, /*!< 256 = 1.024us = 976.5625kHz */ - BCM2835_SPI_CLOCK_DIVIDER_128 = 128, /*!< 128 = 512ns = = 1.953125MHz */ - BCM2835_SPI_CLOCK_DIVIDER_64 = 64, /*!< 64 = 256ns = 3.90625MHz */ - BCM2835_SPI_CLOCK_DIVIDER_32 = 32, /*!< 32 = 128ns = 7.8125MHz */ - BCM2835_SPI_CLOCK_DIVIDER_16 = 16, /*!< 16 = 64ns = 15.625MHz */ - BCM2835_SPI_CLOCK_DIVIDER_8 = 8, /*!< 8 = 32ns = 31.25MHz */ - BCM2835_SPI_CLOCK_DIVIDER_4 = 4, /*!< 4 = 16ns = 62.5MHz */ - BCM2835_SPI_CLOCK_DIVIDER_2 = 2, /*!< 2 = 8ns = 125MHz, fastest you can get */ - BCM2835_SPI_CLOCK_DIVIDER_1 = 1 /*!< 1 = 262.144us = 3.814697260kHz, same as 0/65536 */ + BCM2835_SPI_CLOCK_DIVIDER_65536 = 0, /*!< 65536 = 3.814697260kHz on Rpi2, 6.1035156kHz on RPI3 */ + BCM2835_SPI_CLOCK_DIVIDER_32768 = 32768, /*!< 32768 = 7.629394531kHz on Rpi2, 12.20703125kHz on RPI3 */ + BCM2835_SPI_CLOCK_DIVIDER_16384 = 16384, /*!< 16384 = 15.25878906kHz on Rpi2, 24.4140625kHz on RPI3 */ + BCM2835_SPI_CLOCK_DIVIDER_8192 = 8192, /*!< 8192 = 30.51757813kHz on Rpi2, 48.828125kHz on RPI3 */ + BCM2835_SPI_CLOCK_DIVIDER_4096 = 4096, /*!< 4096 = 61.03515625kHz on Rpi2, 97.65625kHz on RPI3 */ + BCM2835_SPI_CLOCK_DIVIDER_2048 = 2048, /*!< 2048 = 122.0703125kHz on Rpi2, 195.3125kHz on RPI3 */ + BCM2835_SPI_CLOCK_DIVIDER_1024 = 1024, /*!< 1024 = 244.140625kHz on Rpi2, 390.625kHz on RPI3 */ + BCM2835_SPI_CLOCK_DIVIDER_512 = 512, /*!< 512 = 488.28125kHz on Rpi2, 781.25kHz on RPI3 */ + BCM2835_SPI_CLOCK_DIVIDER_256 = 256, /*!< 256 = 976.5625kHz on Rpi2, 1.5625MHz on RPI3 */ + BCM2835_SPI_CLOCK_DIVIDER_128 = 128, /*!< 128 = 1.953125MHz on Rpi2, 3.125MHz on RPI3 */ + BCM2835_SPI_CLOCK_DIVIDER_64 = 64, /*!< 64 = 3.90625MHz on Rpi2, 6.250MHz on RPI3 */ + BCM2835_SPI_CLOCK_DIVIDER_32 = 32, /*!< 32 = 7.8125MHz on Rpi2, 12.5MHz on RPI3 */ + BCM2835_SPI_CLOCK_DIVIDER_16 = 16, /*!< 16 = 15.625MHz on Rpi2, 25MHz on RPI3 */ + BCM2835_SPI_CLOCK_DIVIDER_8 = 8, /*!< 8 = 31.25MHz on Rpi2, 50MHz on RPI3 */ + BCM2835_SPI_CLOCK_DIVIDER_4 = 4, /*!< 4 = 62.5MHz on Rpi2, 100MHz on RPI3. Dont expect this speed to work reliably. */ + BCM2835_SPI_CLOCK_DIVIDER_2 = 2, /*!< 2 = 125MHz on Rpi2, 200MHz on RPI3, fastest you can get. Dont expect this speed to work reliably.*/ + BCM2835_SPI_CLOCK_DIVIDER_1 = 1 /*!< 1 = 3.814697260kHz on Rpi2, 6.1035156kHz on RPI3, same as 0/65536 */ } bcm2835SPIClockDivider; /* Defines for I2C @@ -1313,12 +1330,14 @@ extern "C" { extern void bcm2835_gpio_pudclk(uint8_t pin, uint8_t on); /*! Reads and returns the Pad Control for the given GPIO group. + Caution: requires root access. \param[in] group The GPIO pad group number, one of BCM2835_PAD_GROUP_GPIO_* \return Mask of bits from BCM2835_PAD_* from \ref bcm2835PadGroup */ extern uint32_t bcm2835_gpio_pad(uint8_t group); /*! Sets the Pad Control for the given GPIO group. + Caution: requires root access. \param[in] group The GPIO pad group number, one of BCM2835_PAD_GROUP_GPIO_* \param[in] control Mask of bits from BCM2835_PAD_* from \ref bcm2835PadGroup. Note that it is not necessary to include BCM2835_PAD_PASSWRD in the mask as this