mirror of https://github.com/OpenIPC/firmware.git
Add i2c-telemetry, Fix hisi_gpio, Add memdump, Add Novatek profiles
parent
9431f437d5
commit
d3486717eb
|
@ -0,0 +1,129 @@
|
||||||
|
name: OpenIPC for NT98562
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build_core:
|
||||||
|
name: OpenIPC v2.1 for NT98562
|
||||||
|
runs-on: ubuntu-18.04
|
||||||
|
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- name: Checkout
|
||||||
|
id: checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install build dependencies
|
||||||
|
id: install
|
||||||
|
run: |
|
||||||
|
make install-deps
|
||||||
|
mkdir -p tmp
|
||||||
|
|
||||||
|
- name: Free disk space
|
||||||
|
id: freshing
|
||||||
|
run: |
|
||||||
|
sudo swapoff -a
|
||||||
|
sudo rm -f /swapfile
|
||||||
|
sudo apt clean
|
||||||
|
docker rmi $(docker image ls -aq)
|
||||||
|
df -h
|
||||||
|
|
||||||
|
- name: Prepare buildroot
|
||||||
|
id: prepare
|
||||||
|
run: |
|
||||||
|
HEAD_TAG=$(git tag --points-at HEAD)
|
||||||
|
GIT_HASH=$(git rev-parse --short $GITHUB_SHA)
|
||||||
|
BRANCH_NAME=$(echo $GITHUB_REF | cut -d'/' -f 3)
|
||||||
|
if [ -z "$HEAD_TAG" ]; then
|
||||||
|
TAG_NAME="latest"
|
||||||
|
RELEASE_NAME="Development Build"
|
||||||
|
PRERELEASE=true
|
||||||
|
else
|
||||||
|
TAG_NAME=${{ github.ref }}
|
||||||
|
RELEASE_NAME="Release ${{ github.ref }}"
|
||||||
|
PRERELEASE=false
|
||||||
|
fi
|
||||||
|
echo "GIT_HASH=$GIT_HASH" >> $GITHUB_ENV
|
||||||
|
echo "TAG_NAME=$TAG_NAME" >> $GITHUB_ENV
|
||||||
|
echo "RELEASE_NAME=$RELEASE_NAME" >> $GITHUB_ENV
|
||||||
|
echo "PRERELEASE=$PRERELEASE" >> $GITHUB_ENV
|
||||||
|
echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV
|
||||||
|
cd $GITHUB_WORKSPACE
|
||||||
|
make prepare
|
||||||
|
|
||||||
|
- name: Build NT98562 firmware
|
||||||
|
id: build-nt98562-firmware
|
||||||
|
continue-on-error: true
|
||||||
|
run: |
|
||||||
|
ARCHIVE_FW="${GITHUB_WORKSPACE}/output/images/openipc.nt98562-br.tgz"
|
||||||
|
echo "ARCHIVE_FW=$ARCHIVE_FW" >> $GITHUB_ENV
|
||||||
|
cd $GITHUB_WORKSPACE
|
||||||
|
make PLATFORM=sigmastar BOARD=unknown_unknown_nt98562_openipc all
|
||||||
|
[[ $(stat --printf="%s" ${GITHUB_WORKSPACE}/output/images/uImage) -gt 2097152 ]] && echo "TG_NOTIFY=Warning, kernel size exceeded : $(stat --printf="%s" ${GITHUB_WORKSPACE}/output/images/uImage) vs 2097152" >> $GITHUB_ENV && exit 1
|
||||||
|
[[ $(stat --printf="%s" ${GITHUB_WORKSPACE}/output/images/rootfs.squashfs) -gt 5242880 ]] && echo "TG_NOTIFY=Warning, rootfs size exceeded - $(stat --printf="%s" ${GITHUB_WORKSPACE}/output/images/rootfs.squashfs) vs 5242880" >> $GITHUB_ENV && exit 1
|
||||||
|
mv ${GITHUB_WORKSPACE}/output/images/uImage ${GITHUB_WORKSPACE}/output/images/uImage.nt98562
|
||||||
|
mv ${GITHUB_WORKSPACE}/output/images/rootfs.squashfs ${GITHUB_WORKSPACE}/output/images/rootfs.squashfs.nt98562
|
||||||
|
tar -C ${GITHUB_WORKSPACE}/output/images -cvzf $ARCHIVE_FW rootfs.squashfs.nt98562 uImage.nt98562
|
||||||
|
|
||||||
|
- name: Build NT98562 SDK
|
||||||
|
id: build-nt98562-sdk
|
||||||
|
continue-on-error: true
|
||||||
|
run: |
|
||||||
|
ARCHIVE_SDK="${GITHUB_WORKSPACE}/output/images/arm-openipc-linux-musleabi_sdk-buildroot.tar.gz"
|
||||||
|
echo "ARCHIVE_SDK=$ARCHIVE_SDK" >> $GITHUB_ENV
|
||||||
|
cd $GITHUB_WORKSPACE/output
|
||||||
|
make sdk
|
||||||
|
|
||||||
|
- name: Send warning message to telegram channel
|
||||||
|
env:
|
||||||
|
TG_TOKEN: ${{ secrets.TELEGRAM_TOKEN_BOT_OPENIPC }}
|
||||||
|
TG_CHANNEL: ${{ secrets.TELEGRAM_CHANNEL_OPENIPC_DEV }}
|
||||||
|
if: steps.build-nt98562-firmware.outcome != 'success' || steps.build-nt98562-sdk.outcome != 'success'
|
||||||
|
run: |
|
||||||
|
TG_OPTIONS="-s --connect-timeout 5 --max-time 15"
|
||||||
|
TG_NOTIFY="${TG_NOTIFY:=Warning, Buildroot compiling error...}"
|
||||||
|
TG_HEADER=$(echo -e "\r\n$TG_NOTIFY \r\n\r\nCommit: $GIT_HASH \r\nBranch: $BRANCH_NAME \r\nTag: $TAG_NAME \r\n\r\n\xE2\x9A\xA0 GitHub Actions")
|
||||||
|
curl $TG_OPTIONS -H "Content-Type: multipart/form-data" -X POST https://api.telegram.org/bot$TG_TOKEN/sendMessage \
|
||||||
|
-F chat_id=$TG_CHANNEL -F text="$TG_HEADER"
|
||||||
|
|
||||||
|
- name: Create release
|
||||||
|
uses: actions/create-release@v1
|
||||||
|
continue-on-error: true
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
tag_name: ${{ env.TAG_NAME }}
|
||||||
|
release_name: ${{ env.RELEASE_NAME }}
|
||||||
|
draft: false
|
||||||
|
prerelease: ${{ env.PRERELEASE }}
|
||||||
|
|
||||||
|
- name: Upload FW to release
|
||||||
|
uses: svenstaro/upload-release-action@v2
|
||||||
|
continue-on-error: true
|
||||||
|
with:
|
||||||
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
file: ${{ env.ARCHIVE_FW }}
|
||||||
|
asset_name: "openipc.nt98562-br.tgz"
|
||||||
|
tag: ${{ env.TAG_NAME }}
|
||||||
|
overwrite: true
|
||||||
|
|
||||||
|
- name: Upload SDK to release
|
||||||
|
uses: svenstaro/upload-release-action@v2
|
||||||
|
continue-on-error: true
|
||||||
|
with:
|
||||||
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
file: ${{ env.ARCHIVE_SDK }}
|
||||||
|
asset_name: "arm-openipc-nt98562-linux-musleabi_sdk-buildroot.tar.gz"
|
||||||
|
tag: ${{ env.TAG_NAME }}
|
||||||
|
overwrite: true
|
||||||
|
|
||||||
|
- name: Send binary file to telegram channel
|
||||||
|
env:
|
||||||
|
TG_TOKEN: ${{ secrets.TELEGRAM_TOKEN_BOT_OPENIPC }}
|
||||||
|
TG_CHANNEL: ${{ secrets.TELEGRAM_CHANNEL_OPENIPC_DEV }}
|
||||||
|
run: |
|
||||||
|
TG_OPTIONS="-s --connect-timeout 5 --max-time 15"
|
||||||
|
TG_HEADER=$(echo -e "\r\nCommit: $GIT_HASH \r\nBranch: $BRANCH_NAME \r\nTag: $TAG_NAME \r\n\r\n\xE2\x9C\x85 GitHub Actions")
|
||||||
|
curl $TG_OPTIONS -H "Content-Type: multipart/form-data" -X POST https://api.telegram.org/bot$TG_TOKEN/sendDocument \
|
||||||
|
-F chat_id=$TG_CHANNEL -F document="@$ARCHIVE_FW" -F caption="$TG_HEADER"
|
|
@ -0,0 +1,129 @@
|
||||||
|
name: OpenIPC for NT98566
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build_core:
|
||||||
|
name: OpenIPC v2.1 for NT98566
|
||||||
|
runs-on: ubuntu-18.04
|
||||||
|
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- name: Checkout
|
||||||
|
id: checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install build dependencies
|
||||||
|
id: install
|
||||||
|
run: |
|
||||||
|
make install-deps
|
||||||
|
mkdir -p tmp
|
||||||
|
|
||||||
|
- name: Free disk space
|
||||||
|
id: freshing
|
||||||
|
run: |
|
||||||
|
sudo swapoff -a
|
||||||
|
sudo rm -f /swapfile
|
||||||
|
sudo apt clean
|
||||||
|
docker rmi $(docker image ls -aq)
|
||||||
|
df -h
|
||||||
|
|
||||||
|
- name: Prepare buildroot
|
||||||
|
id: prepare
|
||||||
|
run: |
|
||||||
|
HEAD_TAG=$(git tag --points-at HEAD)
|
||||||
|
GIT_HASH=$(git rev-parse --short $GITHUB_SHA)
|
||||||
|
BRANCH_NAME=$(echo $GITHUB_REF | cut -d'/' -f 3)
|
||||||
|
if [ -z "$HEAD_TAG" ]; then
|
||||||
|
TAG_NAME="latest"
|
||||||
|
RELEASE_NAME="Development Build"
|
||||||
|
PRERELEASE=true
|
||||||
|
else
|
||||||
|
TAG_NAME=${{ github.ref }}
|
||||||
|
RELEASE_NAME="Release ${{ github.ref }}"
|
||||||
|
PRERELEASE=false
|
||||||
|
fi
|
||||||
|
echo "GIT_HASH=$GIT_HASH" >> $GITHUB_ENV
|
||||||
|
echo "TAG_NAME=$TAG_NAME" >> $GITHUB_ENV
|
||||||
|
echo "RELEASE_NAME=$RELEASE_NAME" >> $GITHUB_ENV
|
||||||
|
echo "PRERELEASE=$PRERELEASE" >> $GITHUB_ENV
|
||||||
|
echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV
|
||||||
|
cd $GITHUB_WORKSPACE
|
||||||
|
make prepare
|
||||||
|
|
||||||
|
- name: Build NT98566 firmware
|
||||||
|
id: build-nt98566-firmware
|
||||||
|
continue-on-error: true
|
||||||
|
run: |
|
||||||
|
ARCHIVE_FW="${GITHUB_WORKSPACE}/output/images/openipc.nt98566-br.tgz"
|
||||||
|
echo "ARCHIVE_FW=$ARCHIVE_FW" >> $GITHUB_ENV
|
||||||
|
cd $GITHUB_WORKSPACE
|
||||||
|
make PLATFORM=sigmastar BOARD=unknown_unknown_nt98566_openipc all
|
||||||
|
[[ $(stat --printf="%s" ${GITHUB_WORKSPACE}/output/images/uImage) -gt 2097152 ]] && echo "TG_NOTIFY=Warning, kernel size exceeded : $(stat --printf="%s" ${GITHUB_WORKSPACE}/output/images/uImage) vs 2097152" >> $GITHUB_ENV && exit 1
|
||||||
|
[[ $(stat --printf="%s" ${GITHUB_WORKSPACE}/output/images/rootfs.squashfs) -gt 5242880 ]] && echo "TG_NOTIFY=Warning, rootfs size exceeded - $(stat --printf="%s" ${GITHUB_WORKSPACE}/output/images/rootfs.squashfs) vs 5242880" >> $GITHUB_ENV && exit 1
|
||||||
|
mv ${GITHUB_WORKSPACE}/output/images/uImage ${GITHUB_WORKSPACE}/output/images/uImage.nt98566
|
||||||
|
mv ${GITHUB_WORKSPACE}/output/images/rootfs.squashfs ${GITHUB_WORKSPACE}/output/images/rootfs.squashfs.nt98566
|
||||||
|
tar -C ${GITHUB_WORKSPACE}/output/images -cvzf $ARCHIVE_FW rootfs.squashfs.nt98566 uImage.nt98566
|
||||||
|
|
||||||
|
- name: Build NT98566 SDK
|
||||||
|
id: build-nt98566-sdk
|
||||||
|
continue-on-error: true
|
||||||
|
run: |
|
||||||
|
ARCHIVE_SDK="${GITHUB_WORKSPACE}/output/images/arm-openipc-linux-musleabi_sdk-buildroot.tar.gz"
|
||||||
|
echo "ARCHIVE_SDK=$ARCHIVE_SDK" >> $GITHUB_ENV
|
||||||
|
cd $GITHUB_WORKSPACE/output
|
||||||
|
make sdk
|
||||||
|
|
||||||
|
- name: Send warning message to telegram channel
|
||||||
|
env:
|
||||||
|
TG_TOKEN: ${{ secrets.TELEGRAM_TOKEN_BOT_OPENIPC }}
|
||||||
|
TG_CHANNEL: ${{ secrets.TELEGRAM_CHANNEL_OPENIPC_DEV }}
|
||||||
|
if: steps.build-nt98566-firmware.outcome != 'success' || steps.build-nt98566-sdk.outcome != 'success'
|
||||||
|
run: |
|
||||||
|
TG_OPTIONS="-s --connect-timeout 5 --max-time 15"
|
||||||
|
TG_NOTIFY="${TG_NOTIFY:=Warning, Buildroot compiling error...}"
|
||||||
|
TG_HEADER=$(echo -e "\r\n$TG_NOTIFY \r\n\r\nCommit: $GIT_HASH \r\nBranch: $BRANCH_NAME \r\nTag: $TAG_NAME \r\n\r\n\xE2\x9A\xA0 GitHub Actions")
|
||||||
|
curl $TG_OPTIONS -H "Content-Type: multipart/form-data" -X POST https://api.telegram.org/bot$TG_TOKEN/sendMessage \
|
||||||
|
-F chat_id=$TG_CHANNEL -F text="$TG_HEADER"
|
||||||
|
|
||||||
|
- name: Create release
|
||||||
|
uses: actions/create-release@v1
|
||||||
|
continue-on-error: true
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
tag_name: ${{ env.TAG_NAME }}
|
||||||
|
release_name: ${{ env.RELEASE_NAME }}
|
||||||
|
draft: false
|
||||||
|
prerelease: ${{ env.PRERELEASE }}
|
||||||
|
|
||||||
|
- name: Upload FW to release
|
||||||
|
uses: svenstaro/upload-release-action@v2
|
||||||
|
continue-on-error: true
|
||||||
|
with:
|
||||||
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
file: ${{ env.ARCHIVE_FW }}
|
||||||
|
asset_name: "openipc.nt98566-br.tgz"
|
||||||
|
tag: ${{ env.TAG_NAME }}
|
||||||
|
overwrite: true
|
||||||
|
|
||||||
|
- name: Upload SDK to release
|
||||||
|
uses: svenstaro/upload-release-action@v2
|
||||||
|
continue-on-error: true
|
||||||
|
with:
|
||||||
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
file: ${{ env.ARCHIVE_SDK }}
|
||||||
|
asset_name: "arm-openipc-nt98566-linux-musleabi_sdk-buildroot.tar.gz"
|
||||||
|
tag: ${{ env.TAG_NAME }}
|
||||||
|
overwrite: true
|
||||||
|
|
||||||
|
- name: Send binary file to telegram channel
|
||||||
|
env:
|
||||||
|
TG_TOKEN: ${{ secrets.TELEGRAM_TOKEN_BOT_OPENIPC }}
|
||||||
|
TG_CHANNEL: ${{ secrets.TELEGRAM_CHANNEL_OPENIPC_DEV }}
|
||||||
|
run: |
|
||||||
|
TG_OPTIONS="-s --connect-timeout 5 --max-time 15"
|
||||||
|
TG_HEADER=$(echo -e "\r\nCommit: $GIT_HASH \r\nBranch: $BRANCH_NAME \r\nTag: $TAG_NAME \r\n\r\n\xE2\x9C\x85 GitHub Actions")
|
||||||
|
curl $TG_OPTIONS -H "Content-Type: multipart/form-data" -X POST https://api.telegram.org/bot$TG_TOKEN/sendDocument \
|
||||||
|
-F chat_id=$TG_CHANNEL -F document="@$ARCHIVE_FW" -F caption="$TG_HEADER"
|
|
@ -3,7 +3,7 @@ source "$BR2_EXTERNAL_HISILICON_PATH/package/hisi_patcher/Config.in"
|
||||||
source "$BR2_EXTERNAL_HISILICON_PATH/package/aura-httpd/Config.in"
|
source "$BR2_EXTERNAL_HISILICON_PATH/package/aura-httpd/Config.in"
|
||||||
source "$BR2_EXTERNAL_HISILICON_PATH/package/fwprintenv-ng/Config.in"
|
source "$BR2_EXTERNAL_HISILICON_PATH/package/fwprintenv-ng/Config.in"
|
||||||
source "$BR2_EXTERNAL_HISILICON_PATH/package/gdbserver-lite/Config.in"
|
source "$BR2_EXTERNAL_HISILICON_PATH/package/gdbserver-lite/Config.in"
|
||||||
source "$BR2_EXTERNAL_HISILICON_PATH/package/hisi_gpio_scanner/Config.in"
|
source "$BR2_EXTERNAL_HISILICON_PATH/package/hisi_gpio/Config.in"
|
||||||
source "$BR2_EXTERNAL_HISILICON_PATH/package/hisilicon-osdrv4/Config.in"
|
source "$BR2_EXTERNAL_HISILICON_PATH/package/hisilicon-osdrv4/Config.in"
|
||||||
source "$BR2_EXTERNAL_HISILICON_PATH/package/ipctool/Config.in"
|
source "$BR2_EXTERNAL_HISILICON_PATH/package/ipctool/Config.in"
|
||||||
source "$BR2_EXTERNAL_HISILICON_PATH/package/libevent-mini/Config.in"
|
source "$BR2_EXTERNAL_HISILICON_PATH/package/libevent-mini/Config.in"
|
||||||
|
|
|
@ -49,7 +49,7 @@ BR2_PACKAGE_BUSYBOX_CONFIG="$(TOPDIR)/../general/package/busybox/busybox.config"
|
||||||
BR2_PACKAGE_DROPBEAR=y
|
BR2_PACKAGE_DROPBEAR=y
|
||||||
BR2_PACKAGE_FWPRINTENV_NG=y
|
BR2_PACKAGE_FWPRINTENV_NG=y
|
||||||
# BR2_PACKAGE_HASERL is not set
|
# BR2_PACKAGE_HASERL is not set
|
||||||
BR2_PACKAGE_HISI_GPIO_SCANNER=y
|
BR2_PACKAGE_HISI_GPIO=y
|
||||||
BR2_PACKAGE_HISILICON_OSDRV4=y
|
BR2_PACKAGE_HISILICON_OSDRV4=y
|
||||||
BR2_PACKAGE_IPCTOOL=y
|
BR2_PACKAGE_IPCTOOL=y
|
||||||
BR2_PACKAGE_JSON_C=y
|
BR2_PACKAGE_JSON_C=y
|
||||||
|
|
|
@ -50,7 +50,7 @@ BR2_PACKAGE_BUSYBOX_CONFIG="$(TOPDIR)/../general/package/busybox/busybox.config"
|
||||||
BR2_PACKAGE_DROPBEAR=y
|
BR2_PACKAGE_DROPBEAR=y
|
||||||
BR2_PACKAGE_FWPRINTENV_NG=y
|
BR2_PACKAGE_FWPRINTENV_NG=y
|
||||||
#BR2_PACKAGE_HASERL is not set
|
#BR2_PACKAGE_HASERL is not set
|
||||||
BR2_PACKAGE_HISI_GPIO_SCANNER=y
|
BR2_PACKAGE_HISI_GPIO=y
|
||||||
BR2_PACKAGE_HISILICON_OSDRV4=y
|
BR2_PACKAGE_HISILICON_OSDRV4=y
|
||||||
BR2_PACKAGE_IPCTOOL=y
|
BR2_PACKAGE_IPCTOOL=y
|
||||||
BR2_PACKAGE_JSON_C=y
|
BR2_PACKAGE_JSON_C=y
|
||||||
|
|
|
@ -53,7 +53,7 @@ BR2_PACKAGE_BUSYBOX_CONFIG="$(TOPDIR)/../general/package/busybox/busybox.config"
|
||||||
BR2_PACKAGE_DROPBEAR=y
|
BR2_PACKAGE_DROPBEAR=y
|
||||||
BR2_PACKAGE_FWPRINTENV_NG=y
|
BR2_PACKAGE_FWPRINTENV_NG=y
|
||||||
# BR2_PACKAGE_HASERL is not set
|
# BR2_PACKAGE_HASERL is not set
|
||||||
BR2_PACKAGE_HISI_GPIO_SCANNER=y
|
BR2_PACKAGE_HISI_GPIO=y
|
||||||
BR2_PACKAGE_HISILICON_OSDRV4=y
|
BR2_PACKAGE_HISILICON_OSDRV4=y
|
||||||
BR2_PACKAGE_IPCTOOL=y
|
BR2_PACKAGE_IPCTOOL=y
|
||||||
BR2_PACKAGE_JSON_C=y
|
BR2_PACKAGE_JSON_C=y
|
||||||
|
|
|
@ -49,7 +49,7 @@ BR2_PACKAGE_BUSYBOX_CONFIG="$(TOPDIR)/../general/package/busybox/busybox.config"
|
||||||
BR2_PACKAGE_DROPBEAR=y
|
BR2_PACKAGE_DROPBEAR=y
|
||||||
BR2_PACKAGE_FWPRINTENV_NG=y
|
BR2_PACKAGE_FWPRINTENV_NG=y
|
||||||
# BR2_PACKAGE_HASERL is not set
|
# BR2_PACKAGE_HASERL is not set
|
||||||
BR2_PACKAGE_HISI_GPIO_SCANNER=y
|
BR2_PACKAGE_HISI_GPIO=y
|
||||||
BR2_PACKAGE_HISILICON_OSDRV4=y
|
BR2_PACKAGE_HISILICON_OSDRV4=y
|
||||||
BR2_PACKAGE_IPCTOOL=y
|
BR2_PACKAGE_IPCTOOL=y
|
||||||
BR2_PACKAGE_JSON_C=y
|
BR2_PACKAGE_JSON_C=y
|
||||||
|
|
|
@ -49,7 +49,7 @@ BR2_PACKAGE_BUSYBOX_CONFIG="$(TOPDIR)/../general/package/busybox/busybox.config"
|
||||||
BR2_PACKAGE_DROPBEAR=y
|
BR2_PACKAGE_DROPBEAR=y
|
||||||
BR2_PACKAGE_FWPRINTENV_NG=y
|
BR2_PACKAGE_FWPRINTENV_NG=y
|
||||||
# BR2_PACKAGE_HASERL is not set
|
# BR2_PACKAGE_HASERL is not set
|
||||||
BR2_PACKAGE_HISI_GPIO_SCANNER=y
|
BR2_PACKAGE_HISI_GPIO=y
|
||||||
BR2_PACKAGE_HISILICON_OSDRV4=y
|
BR2_PACKAGE_HISILICON_OSDRV4=y
|
||||||
BR2_PACKAGE_IPCTOOL=y
|
BR2_PACKAGE_IPCTOOL=y
|
||||||
BR2_PACKAGE_JSON_C=y
|
BR2_PACKAGE_JSON_C=y
|
||||||
|
|
|
@ -49,7 +49,7 @@ BR2_PACKAGE_BUSYBOX_CONFIG="$(TOPDIR)/../general/package/busybox/busybox.config"
|
||||||
BR2_PACKAGE_DROPBEAR=y
|
BR2_PACKAGE_DROPBEAR=y
|
||||||
BR2_PACKAGE_FWPRINTENV_NG=y
|
BR2_PACKAGE_FWPRINTENV_NG=y
|
||||||
# BR2_PACKAGE_HASERL is not set
|
# BR2_PACKAGE_HASERL is not set
|
||||||
BR2_PACKAGE_HISI_GPIO_SCANNER=y
|
BR2_PACKAGE_HISI_GPIO=y
|
||||||
BR2_PACKAGE_HISILICON_OSDRV4=y
|
BR2_PACKAGE_HISILICON_OSDRV4=y
|
||||||
BR2_PACKAGE_IPCTOOL=y
|
BR2_PACKAGE_IPCTOOL=y
|
||||||
BR2_PACKAGE_JSON_C=y
|
BR2_PACKAGE_JSON_C=y
|
||||||
|
|
|
@ -3,7 +3,7 @@ include $(BR2_EXTERNAL_HISILICON_PATH)/package/hisi_patcher/hisi_patcher.mk
|
||||||
include $(BR2_EXTERNAL_HISILICON_PATH)/package/aura-httpd/aura-httpd.mk
|
include $(BR2_EXTERNAL_HISILICON_PATH)/package/aura-httpd/aura-httpd.mk
|
||||||
include $(BR2_EXTERNAL_HISILICON_PATH)/package/gdbserver-lite/gdbserver-lite.mk
|
include $(BR2_EXTERNAL_HISILICON_PATH)/package/gdbserver-lite/gdbserver-lite.mk
|
||||||
include $(BR2_EXTERNAL_HISILICON_PATH)/package/fwprintenv-ng/fwprintenv-ng.mk
|
include $(BR2_EXTERNAL_HISILICON_PATH)/package/fwprintenv-ng/fwprintenv-ng.mk
|
||||||
include $(BR2_EXTERNAL_HISILICON_PATH)/package/hisi_gpio_scanner/hisi_gpio_scanner.mk
|
include $(BR2_EXTERNAL_HISILICON_PATH)/package/hisi_gpio/hisi_gpio_scanner.mk
|
||||||
include $(BR2_EXTERNAL_HISILICON_PATH)/package/hisilicon-osdrv4/hisilicon-osdrv4.mk
|
include $(BR2_EXTERNAL_HISILICON_PATH)/package/hisilicon-osdrv4/hisilicon-osdrv4.mk
|
||||||
include $(BR2_EXTERNAL_HISILICON_PATH)/package/ipctool/ipctool.mk
|
include $(BR2_EXTERNAL_HISILICON_PATH)/package/ipctool/ipctool.mk
|
||||||
include $(BR2_EXTERNAL_HISILICON_PATH)/package/libevent-mini/libevent-mini.mk
|
include $(BR2_EXTERNAL_HISILICON_PATH)/package/libevent-mini/libevent-mini.mk
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
config BR2_PACKAGE_HISI_GPIO
|
||||||
|
bool "hisi_gpio"
|
||||||
|
help
|
||||||
|
Utility for diagnosing, displaying GPIO statuses and run commands
|
||||||
|
|
||||||
|
https://openipc.org
|
|
@ -0,0 +1,25 @@
|
||||||
|
################################################################################
|
||||||
|
#
|
||||||
|
# hisi_gpio
|
||||||
|
#
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
HISI_GPIO_LICENSE = MIT
|
||||||
|
HISI_GPIO_LICENSE_FILES = LICENSE
|
||||||
|
|
||||||
|
define HISI_GPIO_EXTRACT_CMDS
|
||||||
|
cp $(BR2_EXTERNAL_HISILICON_PATH)/package/hisi_gpio/src/hisi_gpio_scanner.c $(@D)/
|
||||||
|
cp $(BR2_EXTERNAL_HISILICON_PATH)/package/hisi_gpio/src/hisi_gpio_watcher.c $(@D)/
|
||||||
|
endef
|
||||||
|
|
||||||
|
define HISI_GPIO_BUILD_CMDS
|
||||||
|
(cd $(@D); $(TARGET_CC) -Os -s hisi_gpio_scanner.c -o hisi_gpio_scanner)
|
||||||
|
(cd $(@D); $(TARGET_CC) -Os -s hisi_gpio_watcher.c -o hisi_gpio_watcher)
|
||||||
|
endef
|
||||||
|
|
||||||
|
define HISI_GPIO_INSTALL_TARGET_CMDS
|
||||||
|
install -m 0755 -D $(@D)/hisi_gpio_scanner $(TARGET_DIR)/usr/bin/hisi_gpio_scanner
|
||||||
|
install -m 0755 -D $(@D)/hisi_gpio_watcher $(TARGET_DIR)/usr/bin/hisi_gpio_watcher
|
||||||
|
endef
|
||||||
|
|
||||||
|
$(eval $(generic-package))
|
|
@ -0,0 +1,392 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <setjmp.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
#define SYSFS_GPIO_DIR "/sys/class/gpio"
|
||||||
|
#define MAX_BUF 64
|
||||||
|
|
||||||
|
//#define DEBUG_ENABLE 0 //debug 1
|
||||||
|
|
||||||
|
#define DEFAULT_MD_LEN 128
|
||||||
|
#define PAGE_SIZE 0x1000
|
||||||
|
#define PAGE_SIZE_MASK (~(0xfff))
|
||||||
|
|
||||||
|
int debug;
|
||||||
|
|
||||||
|
typedef struct tag_MMAP_Node
|
||||||
|
{
|
||||||
|
unsigned long Start_P;
|
||||||
|
unsigned long Start_V;
|
||||||
|
unsigned long length;
|
||||||
|
unsigned long refcount;
|
||||||
|
struct tag_MMAP_Node * next;
|
||||||
|
}TMMAP_Node_t;
|
||||||
|
|
||||||
|
TMMAP_Node_t * pTMMAPNode = NULL;
|
||||||
|
int fd = -1;
|
||||||
|
const char dev[]="/dev/mem";
|
||||||
|
jmp_buf *sigbus_jmp; // global
|
||||||
|
|
||||||
|
/****************************************************************
|
||||||
|
* signal_handler
|
||||||
|
****************************************************************/
|
||||||
|
void signal_handler (int sig)
|
||||||
|
{
|
||||||
|
if (sig == SIGBUS)
|
||||||
|
{
|
||||||
|
//printf("signal_handler SIGBUS!\n");
|
||||||
|
if(sigbus_jmp) siglongjmp(*sigbus_jmp, 1);
|
||||||
|
// no one to catch the error, so abort
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/****************************************************************
|
||||||
|
* set_handle
|
||||||
|
****************************************************************/
|
||||||
|
int set_handler()
|
||||||
|
{
|
||||||
|
struct sigaction act;
|
||||||
|
memset (&act, 0, sizeof(act));
|
||||||
|
act.sa_sigaction = (void *)signal_handler;
|
||||||
|
act.sa_flags = SA_SIGINFO;
|
||||||
|
if (sigaction(SIGBUS, &act, 0))
|
||||||
|
{
|
||||||
|
perror ("sigaction");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/****************************************************************
|
||||||
|
* memmap
|
||||||
|
****************************************************************/
|
||||||
|
void * memmap(unsigned long phy_addr, unsigned long size)
|
||||||
|
{
|
||||||
|
unsigned long phy_addr_in_page;
|
||||||
|
unsigned long page_diff;
|
||||||
|
unsigned long size_in_page;
|
||||||
|
unsigned long value = 0;
|
||||||
|
TMMAP_Node_t * pTmp;
|
||||||
|
TMMAP_Node_t * pNew;
|
||||||
|
void *addr=NULL;
|
||||||
|
if(size == 0)
|
||||||
|
{
|
||||||
|
printf("memmap():size can't be zero!\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* check if the physical memory space have been mmaped */
|
||||||
|
pTmp = pTMMAPNode;
|
||||||
|
while(pTmp != NULL)
|
||||||
|
{
|
||||||
|
if( (phy_addr >= pTmp->Start_P) && ( (phy_addr + size) <= (pTmp->Start_P + pTmp->length) ) )
|
||||||
|
{
|
||||||
|
pTmp->refcount++; /* referrence count increase by 1 */
|
||||||
|
return (void *)(pTmp->Start_V + phy_addr - pTmp->Start_P);
|
||||||
|
}
|
||||||
|
pTmp = pTmp->next;
|
||||||
|
}
|
||||||
|
/* not mmaped yet */
|
||||||
|
if(fd < 0)
|
||||||
|
{
|
||||||
|
/* dev not opened yet, so open it */
|
||||||
|
fd = open (dev, O_RDONLY);
|
||||||
|
if(fd < 0)
|
||||||
|
{
|
||||||
|
printf("memmap():open %s error!\n", dev);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* addr align in page_size(4K) */
|
||||||
|
phy_addr_in_page = phy_addr & PAGE_SIZE_MASK;
|
||||||
|
page_diff = phy_addr - phy_addr_in_page;
|
||||||
|
/* size in page_size */
|
||||||
|
size_in_page =((size + page_diff - 1) & PAGE_SIZE_MASK) + PAGE_SIZE;
|
||||||
|
addr = mmap((void *)0, size_in_page, PROT_READ, MAP_SHARED, fd, phy_addr_in_page);
|
||||||
|
if(addr == MAP_FAILED)
|
||||||
|
{
|
||||||
|
printf("memmap():mmap @ 0x%x error!\n", phy_addr_in_page);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* add this mmap to MMAP Node */
|
||||||
|
pNew = (TMMAP_Node_t *)malloc(sizeof(TMMAP_Node_t));
|
||||||
|
if(NULL == pNew)
|
||||||
|
{
|
||||||
|
printf("memmap():malloc new node failed!\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
pNew->Start_P = phy_addr_in_page;
|
||||||
|
pNew->Start_V = (unsigned long)addr;
|
||||||
|
pNew->length = size_in_page;
|
||||||
|
pNew->refcount = 1;
|
||||||
|
pNew->next = NULL;
|
||||||
|
if(pTMMAPNode == NULL)
|
||||||
|
{
|
||||||
|
pTMMAPNode = pNew;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pTmp = pTMMAPNode;
|
||||||
|
while(pTmp->next != NULL)
|
||||||
|
{
|
||||||
|
pTmp = pTmp->next;
|
||||||
|
}
|
||||||
|
pTmp->next = pNew;
|
||||||
|
}
|
||||||
|
return (void *)(addr+page_diff);
|
||||||
|
}
|
||||||
|
/****************************************************************
|
||||||
|
* GetValueRegister
|
||||||
|
****************************************************************/
|
||||||
|
unsigned long GetValueRegister(unsigned long adress)
|
||||||
|
{
|
||||||
|
void *pMem = NULL;
|
||||||
|
unsigned long value = -1;
|
||||||
|
jmp_buf sigbus_jmpbuf;
|
||||||
|
sigbus_jmp = &sigbus_jmpbuf;
|
||||||
|
if(sigsetjmp(sigbus_jmpbuf, 1) == 0)
|
||||||
|
{
|
||||||
|
pMem = memmap(adress,DEFAULT_MD_LEN);
|
||||||
|
if (pMem == NULL)
|
||||||
|
{
|
||||||
|
printf("memmap failed!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
value = *(unsigned int*)pMem;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
/****************************************************************
|
||||||
|
* parse_int
|
||||||
|
****************************************************************/
|
||||||
|
unsigned long parse_int (char *str) {
|
||||||
|
long long result;
|
||||||
|
char *endptr;
|
||||||
|
|
||||||
|
result = strtoll(str, &endptr, 0);
|
||||||
|
if (str == '\0' || *endptr != '\0') {
|
||||||
|
fprintf(stderr, "\"%s\" is not a valid number\n", str);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (unsigned long)result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************
|
||||||
|
* gpio_get_value
|
||||||
|
****************************************************************/
|
||||||
|
int gpio_get_value(unsigned int gpio, unsigned long *value)
|
||||||
|
{
|
||||||
|
int fd, len;
|
||||||
|
char buf[MAX_BUF];
|
||||||
|
char ch;
|
||||||
|
|
||||||
|
len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);
|
||||||
|
|
||||||
|
fd = open(buf, O_RDONLY | O_NONBLOCK);
|
||||||
|
if (fd < 0) {
|
||||||
|
perror("gpio/get-value");
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
read(fd, &ch, 1);
|
||||||
|
|
||||||
|
if (ch != '0') {
|
||||||
|
*value = 1;
|
||||||
|
} else {
|
||||||
|
*value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/****************************************************************
|
||||||
|
* gpio_get_dir
|
||||||
|
****************************************************************/
|
||||||
|
int gpio_get_dir(unsigned int gpio, unsigned long *value)
|
||||||
|
{
|
||||||
|
int fd, len, i;
|
||||||
|
char buf[MAX_BUF];
|
||||||
|
char ch[5];
|
||||||
|
|
||||||
|
len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/direction", gpio);
|
||||||
|
|
||||||
|
|
||||||
|
fd = open(buf, O_RDONLY | O_NONBLOCK);
|
||||||
|
if (fd < 0) {
|
||||||
|
perror("gpio/direction");
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
i = read(fd, ch, 5);
|
||||||
|
ch[i] = 0;
|
||||||
|
|
||||||
|
|
||||||
|
if(!strncmp("in",ch,2)){*value = 0;}
|
||||||
|
else if(!strncmp("out",ch,2)){*value = 1;}
|
||||||
|
else {*value = -1;}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/****************************************************************
|
||||||
|
* check_run
|
||||||
|
****************************************************************/
|
||||||
|
void check_run(unsigned char *runsh, int chkbit, int chkstat, int chkdirect)
|
||||||
|
{
|
||||||
|
if (chkbit==chkstat)
|
||||||
|
{
|
||||||
|
if(debug)
|
||||||
|
{
|
||||||
|
if (chkdirect==1) {printf("Direction: Output\n");} else {printf("Direction: Input\n");}
|
||||||
|
printf("Check Level:%d Current Level:%d\n",chkstat,chkbit);
|
||||||
|
printf("Run Script: %s\n", runsh);}
|
||||||
|
system (runsh);
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (chkstat==-1)
|
||||||
|
{
|
||||||
|
if(debug)
|
||||||
|
{
|
||||||
|
if (chkdirect==1) {printf("Direction: Output\n");} else {printf("Direction: Input\n");}
|
||||||
|
printf("Check Level:%d Current Level:%d\n",chkstat,chkbit);
|
||||||
|
printf("Run Script: %s\n", runsh);}
|
||||||
|
system (runsh);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/******************************************************************************
|
||||||
|
* show usage
|
||||||
|
******************************************************************************/
|
||||||
|
void show_sage(char *sPrgNm, int usgc)
|
||||||
|
{
|
||||||
|
const char gpiou[]="Usage : %s GPIO(gpioN) Status(on|off|both) 'Programm_run'.\n";
|
||||||
|
const char memu[]="Usage : %s GPIO_Base GPIO_Offset GPIO_Group GPIO_Bit Status(on|off|both) 'Programm_run'.\n";
|
||||||
|
|
||||||
|
switch (usgc)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
printf(memu,sPrgNm);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
printf(gpiou,sPrgNm);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf(memu,sPrgNm);
|
||||||
|
printf(gpiou,sPrgNm);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//************************************************************
|
||||||
|
//************************************************************
|
||||||
|
//************************************************************
|
||||||
|
/****************************************************************
|
||||||
|
* main
|
||||||
|
****************************************************************/
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
unsigned int gpio;
|
||||||
|
int sfs = 0;
|
||||||
|
char *stat = NULL;
|
||||||
|
char *cmd = NULL;
|
||||||
|
unsigned long GPIO_Base, GPIO_Offset;
|
||||||
|
unsigned long adress = 0;
|
||||||
|
unsigned long direct = 0;
|
||||||
|
unsigned long value = 0;
|
||||||
|
unsigned long OldValue= 0;
|
||||||
|
int GPIO_Group, GPIO_Bit, old_bit, new_bit, status;
|
||||||
|
|
||||||
|
if(set_handler()==-1)
|
||||||
|
{
|
||||||
|
printf("Set handler Error!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( (argc < 2))
|
||||||
|
{
|
||||||
|
show_sage(argv[0], 0);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug = (argv[0][strlen(argv[0])-1])- '0'; //debug ON
|
||||||
|
if ((debug) == 1){ printf("Debug ON!\n"); }
|
||||||
|
|
||||||
|
|
||||||
|
if ((sscanf (argv[1], "gpio%d", &gpio) == 1) || (!strncmp("gpio",argv[1],4)))
|
||||||
|
{
|
||||||
|
if (argc != 4) {
|
||||||
|
show_sage(argv[0], 2);
|
||||||
|
exit(EXIT_FAILURE);}
|
||||||
|
|
||||||
|
sfs = 1;
|
||||||
|
stat = malloc(strlen(argv[2]));
|
||||||
|
strcpy(stat, argv[2]); //Status_on|off|both
|
||||||
|
cmd = malloc(strlen(argv[3]));
|
||||||
|
strcpy(cmd, argv[3]); //Programm_run
|
||||||
|
gpio_get_value(gpio, &OldValue); //Save current value
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (argc != 7) {
|
||||||
|
show_sage(argv[0], 1);
|
||||||
|
exit(EXIT_FAILURE);}
|
||||||
|
|
||||||
|
GPIO_Base=parse_int(argv[1]); //GPIO_Base
|
||||||
|
GPIO_Offset=parse_int(argv[2]); //GPIO_Offset
|
||||||
|
GPIO_Group=atoi(argv[3]); //GPIO_Group
|
||||||
|
GPIO_Bit = atoi(argv[4]); //GPIO_Bit
|
||||||
|
stat = malloc(strlen(argv[5]));
|
||||||
|
strcpy(stat, argv[5]); //Status_on|off|both
|
||||||
|
cmd = malloc(strlen(argv[6]));
|
||||||
|
strcpy(cmd, argv[6]); //Programm_run
|
||||||
|
}
|
||||||
|
//Status
|
||||||
|
if(!strcmp("on",stat)){status = 1;} //on = 1
|
||||||
|
else if(!strcmp("off",stat)){status = 0;} //off = 0
|
||||||
|
else if(!strcmp("both",stat)){status = -1;} //both = -1 (The script is executed twice)
|
||||||
|
else {status = -1;}
|
||||||
|
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
if (sfs == 0)
|
||||||
|
{
|
||||||
|
adress=GPIO_Base+(GPIO_Group*GPIO_Offset)+0x3fc;
|
||||||
|
value = GetValueRegister(adress);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
gpio_get_value(gpio, &value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(OldValue!=value)
|
||||||
|
{
|
||||||
|
if (sfs == 0){
|
||||||
|
old_bit = (OldValue>>GPIO_Bit)&1;
|
||||||
|
new_bit = (value>>GPIO_Bit)&1;
|
||||||
|
|
||||||
|
if(old_bit!=new_bit)
|
||||||
|
{
|
||||||
|
adress=GPIO_Base+(GPIO_Group*GPIO_Offset)+0x400;
|
||||||
|
direct = GetValueRegister(adress);
|
||||||
|
direct = (direct>>GPIO_Bit)&1;
|
||||||
|
adress=GPIO_Base+(GPIO_Group*GPIO_Offset)+(1<<GPIO_Bit+2);
|
||||||
|
check_run(cmd,new_bit,status,direct);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
gpio_get_dir(gpio, &direct);
|
||||||
|
check_run(cmd,value,status,direct);
|
||||||
|
}
|
||||||
|
|
||||||
|
OldValue=value;
|
||||||
|
}
|
||||||
|
usleep(250000);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
//************************************************************
|
||||||
|
//************************************************************
|
||||||
|
//************************************************************
|
|
@ -1,6 +0,0 @@
|
||||||
config BR2_PACKAGE_HISI_GPIO_SCANNER
|
|
||||||
bool "hisi_gpio_scanner"
|
|
||||||
help
|
|
||||||
Utility for diagnosing and displaying GPIO statuses
|
|
||||||
|
|
||||||
https://openipc.org
|
|
|
@ -1,22 +0,0 @@
|
||||||
################################################################################
|
|
||||||
#
|
|
||||||
# hisi_gpio_scanner
|
|
||||||
#
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
HISI_GPIO_SCANNER_LICENSE = MIT
|
|
||||||
HISI_GPIO_SCANNER_LICENSE_FILES = LICENSE
|
|
||||||
|
|
||||||
define HISI_GPIO_SCANNER_EXTRACT_CMDS
|
|
||||||
cp $(BR2_EXTERNAL_HISILICON_PATH)/package/hisi_gpio_scanner/src/hisi_gpio_scanner.c $(@D)/
|
|
||||||
endef
|
|
||||||
|
|
||||||
define HISI_GPIO_SCANNER_BUILD_CMDS
|
|
||||||
(cd $(@D); $(TARGET_CC) -Os -s hisi_gpio_scanner.c -o hisi_gpio_scanner)
|
|
||||||
endef
|
|
||||||
|
|
||||||
define HISI_GPIO_SCANNER_INSTALL_TARGET_CMDS
|
|
||||||
install -m 0755 -D $(@D)/hisi_gpio_scanner $(TARGET_DIR)/usr/bin/hisi_gpio_scanner
|
|
||||||
endef
|
|
||||||
|
|
||||||
$(eval $(generic-package))
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,83 @@
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h> // open
|
||||||
|
#include <sys/stat.h> // open
|
||||||
|
#include <fcntl.h> // open
|
||||||
|
#include <unistd.h> // read/write usleep
|
||||||
|
#include <stdlib.h> // exit
|
||||||
|
#include <inttypes.h> // uint8_t, etc
|
||||||
|
#include <linux/i2c-dev.h> // I2C bus definitions
|
||||||
|
|
||||||
|
float getVin(int pin) {
|
||||||
|
|
||||||
|
int fd;
|
||||||
|
int ads_address = 0x48;
|
||||||
|
|
||||||
|
uint8_t buf[10];
|
||||||
|
int16_t val;
|
||||||
|
uint8_t pinCodes[4];
|
||||||
|
|
||||||
|
pinCodes[0]=0xc3;
|
||||||
|
pinCodes[1]=0xd3;
|
||||||
|
pinCodes[2]=0xe3;
|
||||||
|
pinCodes[3]=0xf3;
|
||||||
|
|
||||||
|
// open device on /dev/i2c-0
|
||||||
|
if ((fd = open("/dev/i2c-0", O_RDWR)) < 0) {
|
||||||
|
printf("Error: Couldn't open device! %d\n", fd);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// connect to ads1115 as i2c slave
|
||||||
|
if (ioctl(fd, I2C_SLAVE, ads_address) < 0) {
|
||||||
|
printf("Error: Couldn't find device on address!\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AIN0 and GND, 4.096v, 128s/s
|
||||||
|
|
||||||
|
buf[0] = 1; // config register is 1
|
||||||
|
buf[1] = pinCodes[pin];
|
||||||
|
buf[2] = 0x85;
|
||||||
|
if (write(fd, buf, 3) != 3) {
|
||||||
|
perror("Write to register 1");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
usleep(10000);
|
||||||
|
|
||||||
|
// wait for conversion complete
|
||||||
|
do {
|
||||||
|
if (read(fd, buf, 2) != 2) {
|
||||||
|
perror("Read conversion");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
} while (buf[0] & 0x80 == 0);
|
||||||
|
|
||||||
|
// read conversion register
|
||||||
|
buf[0] = 0; // conversion register is 0
|
||||||
|
if (write(fd, buf, 1) != 1) {
|
||||||
|
perror("Write register select");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
if (read(fd, buf, 2) != 2) {
|
||||||
|
perror("Read conversion");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert output and display results
|
||||||
|
val = (int16_t)buf[0]*256 + (uint16_t)buf[1];
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
return (float)val*4.096/32768.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for ( i=0; i<=3; i++) {
|
||||||
|
printf("Vin%1d (V) %5.3f\n",i,getVin(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,303 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* of the License, 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.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Project Home - https://github.com/takagi/am2321
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h> /* for O_RDWR */
|
||||||
|
#include <string.h> /* for memcpy */
|
||||||
|
#include <linux/i2c-dev.h> /* for I2C_SLAVE */
|
||||||
|
|
||||||
|
#include <unistd.h> /* add by paulerr*/
|
||||||
|
#include <sys/time.h> /* add by paulerr*/
|
||||||
|
|
||||||
|
|
||||||
|
/* I2C character device */
|
||||||
|
#define I2C_DEVICE "/dev/i2c-0"
|
||||||
|
|
||||||
|
/* I2C address of AM2321 sensor in 7 bits
|
||||||
|
* - the first 7 bits should be passed to ioctl system call
|
||||||
|
* because the least 1 bit of the address represents read/write
|
||||||
|
* and the i2c driver takes care of it
|
||||||
|
*/
|
||||||
|
#define AM2321_ADDR (0xB8 >> 1)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* udelay function
|
||||||
|
*/
|
||||||
|
|
||||||
|
long timeval_to_usec( struct timeval tm ) {
|
||||||
|
return tm.tv_sec * 1000000 + tm.tv_usec;
|
||||||
|
}
|
||||||
|
|
||||||
|
void udelay( long us ) {
|
||||||
|
struct timeval current;
|
||||||
|
struct timeval start;
|
||||||
|
|
||||||
|
gettimeofday( &start, NULL );
|
||||||
|
do {
|
||||||
|
gettimeofday( ¤t, NULL );
|
||||||
|
} while( timeval_to_usec( current ) - timeval_to_usec( start ) < us );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CRC16
|
||||||
|
*/
|
||||||
|
|
||||||
|
unsigned short crc16( unsigned char *ptr, unsigned char len ) {
|
||||||
|
unsigned short crc = 0xFFFF;
|
||||||
|
unsigned char i;
|
||||||
|
|
||||||
|
while( len-- )
|
||||||
|
{
|
||||||
|
crc ^= *ptr++;
|
||||||
|
for( i = 0; i < 8; i++ ) {
|
||||||
|
if( crc & 0x01 ) {
|
||||||
|
crc >>= 1;
|
||||||
|
crc ^= 0xA001;
|
||||||
|
} else {
|
||||||
|
crc >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char crc16_low( unsigned short crc ) {
|
||||||
|
return crc & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char crc16_high( unsigned short crc ) {
|
||||||
|
return crc >> 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* st_am2321 Structure
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned char data[8];
|
||||||
|
} st_am2321;
|
||||||
|
|
||||||
|
void __check_crc16( st_am2321 measured ) {
|
||||||
|
unsigned short crc_m, crc_s;
|
||||||
|
|
||||||
|
crc_m = crc16( measured.data, 6 );
|
||||||
|
crc_s = (measured.data[7] << 8) + measured.data[6];
|
||||||
|
if ( crc_m != crc_s ) {
|
||||||
|
fprintf( stderr, "am2321: CRC16 does not match\n" );
|
||||||
|
exit( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
st_am2321 __st_am2321( unsigned char* data ) {
|
||||||
|
st_am2321 result;
|
||||||
|
memcpy( result.data, data, 8 );
|
||||||
|
__check_crc16( result );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void am2321_dump( st_am2321 measured ) {
|
||||||
|
printf( "[ 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x ]\n",
|
||||||
|
measured.data[0], measured.data[1],
|
||||||
|
measured.data[2], measured.data[3],
|
||||||
|
measured.data[4], measured.data[5],
|
||||||
|
measured.data[6], measured.data[7] );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
short __am2321_temperature( st_am2321 measured ) {
|
||||||
|
return (measured.data[4] << 8) + measured.data[5];
|
||||||
|
}
|
||||||
|
|
||||||
|
short am2321_temperature_integral( st_am2321 measured ) {
|
||||||
|
return __am2321_temperature( measured ) / 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
short am2321_temperature_fraction( st_am2321 measured ) {
|
||||||
|
return __am2321_temperature( measured ) % 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
short __am2321_humidity( st_am2321 measured ) {
|
||||||
|
return (measured.data[2] << 8) + measured.data[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
short am2321_humidity_integral( st_am2321 measured ) {
|
||||||
|
return __am2321_humidity( measured ) / 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
short am2321_humidity_fraction( st_am2321 measured ) {
|
||||||
|
return __am2321_humidity( measured ) % 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Measurement function
|
||||||
|
*/
|
||||||
|
|
||||||
|
st_am2321 am2321() {
|
||||||
|
int fd;
|
||||||
|
int ret;
|
||||||
|
int retry_cnt;
|
||||||
|
unsigned char data[8];
|
||||||
|
|
||||||
|
/* open I2C device */
|
||||||
|
fd = open( I2C_DEVICE, O_RDWR );
|
||||||
|
if ( fd < 0 ) {
|
||||||
|
perror( "am2321(1)" );
|
||||||
|
exit( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set address of I2C device in 7 bits */
|
||||||
|
ret = ioctl( fd, I2C_SLAVE, AM2321_ADDR );
|
||||||
|
if ( ret < 0 ) {
|
||||||
|
perror( "am2321(2)" );
|
||||||
|
exit( 2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
retry_cnt = 0;
|
||||||
|
retry:
|
||||||
|
|
||||||
|
/* wake I2C device up */
|
||||||
|
write( fd, NULL, 0);
|
||||||
|
|
||||||
|
/* write measurement request */
|
||||||
|
data[0] = 0x03; data[1] = 0x00; data[2] = 0x04;
|
||||||
|
ret = write( fd, data, 3 );
|
||||||
|
if ( ret < 0 && retry_cnt++ < 5 ) {
|
||||||
|
fprintf( stderr, "am2321: retry\n" );
|
||||||
|
udelay( 1000 );
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
if ( ret < 0 ) {
|
||||||
|
perror( "am2321(3)" );
|
||||||
|
exit( 3 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* wait for having measured */
|
||||||
|
udelay( 1500 );
|
||||||
|
|
||||||
|
/* read measured result */
|
||||||
|
memset( data, 0x00, 8 );
|
||||||
|
ret = read( fd, data, 8 );
|
||||||
|
if ( ret < 0 ) {
|
||||||
|
perror( "am2321(4)" );
|
||||||
|
exit( 4 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* close I2C device */
|
||||||
|
close( fd );
|
||||||
|
|
||||||
|
return __st_am2321( data );
|
||||||
|
}
|
||||||
|
|
||||||
|
st_am2321 am2321_stub() {
|
||||||
|
unsigned char data[] = { 0x03, 0x04, 0x01, 0x41,
|
||||||
|
0x00, 0xEA, 0x21, 0x8F };
|
||||||
|
return __st_am2321( data );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
void print_am2321( st_am2321 measured ) {
|
||||||
|
printf( "%d.%d %d.%d\n",
|
||||||
|
am2321_temperature_integral( measured ),
|
||||||
|
am2321_temperature_fraction( measured ),
|
||||||
|
am2321_humidity_integral( measured ),
|
||||||
|
am2321_humidity_fraction( measured ) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_am2321_human_readable( st_am2321 measured ) {
|
||||||
|
printf( "Temperature (C)\t\t%d.%d\n",
|
||||||
|
am2321_temperature_integral( measured ),
|
||||||
|
am2321_temperature_fraction( measured ) );
|
||||||
|
printf( "Humidity (%%)\t\t%d.%d\n",
|
||||||
|
am2321_humidity_integral( measured ),
|
||||||
|
am2321_humidity_fraction( measured ) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Main
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define OPT_HUMAN_READABLE 0x1
|
||||||
|
#define OPT_STUB 0x2
|
||||||
|
|
||||||
|
int print_help() {
|
||||||
|
fprintf( stderr,
|
||||||
|
"Usage: am2321 [-r] [-s]\n"
|
||||||
|
"Get temperature and humidity measured with Aosong's AM2321 sensor.\n"
|
||||||
|
" -r human readable output\n"
|
||||||
|
" -s not measure with AM2321, instead stub of 23.4[C] and 32.1[%]\n" );
|
||||||
|
exit( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
int parse_options( int argc, char* argv[]) {
|
||||||
|
int options = 0;
|
||||||
|
int flags = 0;
|
||||||
|
|
||||||
|
while( 1+flags < argc && argv[1+flags][0] == '-' ) {
|
||||||
|
switch( argv[1+flags][1] ) {
|
||||||
|
case 'r': options |= OPT_HUMAN_READABLE; break;
|
||||||
|
case 's': options |= OPT_STUB; break;
|
||||||
|
default:
|
||||||
|
fprintf( stderr, "am2321: Unsupported option \"%s\"\n", argv[1+flags] );
|
||||||
|
print_help();
|
||||||
|
exit( 1 );
|
||||||
|
}
|
||||||
|
flags++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
int is_opt_human_readable( int options ) {
|
||||||
|
return options & OPT_HUMAN_READABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int is_opt_stub( int options ) {
|
||||||
|
return options & OPT_STUB;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main( int argc, char* argv[] ) {
|
||||||
|
int options;
|
||||||
|
st_am2321 measured;
|
||||||
|
|
||||||
|
/* parse the given options */
|
||||||
|
options = parse_options( argc, argv );
|
||||||
|
|
||||||
|
/* measure temperature and humidity */
|
||||||
|
measured = ! is_opt_stub( options ) ? am2321() : am2321_stub();
|
||||||
|
|
||||||
|
/* print measured temperature and humidity */
|
||||||
|
if ( ! is_opt_human_readable( options ) ) {
|
||||||
|
print_am2321( measured );
|
||||||
|
} else {
|
||||||
|
print_am2321_human_readable( measured );
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
Sample code for the BH1750
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <linux/i2c-dev.h>
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include "smbus.h"
|
||||||
|
|
||||||
|
#define BH1750FVI_I2C_ADDRESS 0x23 // ADDR > 0.7 VCC)
|
||||||
|
//#define BH1750FVI_I2C_ADDRESS 0x53 // ADDR < 0.3 VCC)
|
||||||
|
#define DEBUG 0
|
||||||
|
|
||||||
|
#define PowerDown 0x00
|
||||||
|
#define PowerOn 0x01
|
||||||
|
#define Reset 0x07
|
||||||
|
#define ContinuHigh 0x10
|
||||||
|
#define ContinuLow 0x13
|
||||||
|
#define OneTimeHigh 0x20
|
||||||
|
#define OneTimeLow 0x23
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
char *fileName = "/dev/i2c-0";
|
||||||
|
int retCode;
|
||||||
|
int readSize;
|
||||||
|
unsigned int res;
|
||||||
|
unsigned int lux;
|
||||||
|
char buf[5];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// Open port for reading and writing
|
||||||
|
if ((fd = open(fileName, O_RDWR)) < 0) {
|
||||||
|
printf("open error\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the port options and set the address of the device
|
||||||
|
if (ioctl(fd, I2C_SLAVE, BH1750FVI_I2C_ADDRESS) < 0) {
|
||||||
|
printf("ioctl error\n");
|
||||||
|
close(fd);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
retCode=i2c_smbus_write_byte(fd, PowerOn);
|
||||||
|
if(DEBUG)printf("Power On retCode=%d\n",retCode);
|
||||||
|
if (retCode < 0) {
|
||||||
|
printf("PowerOn error\n");
|
||||||
|
close(fd);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
retCode=i2c_smbus_write_byte(fd, ContinuHigh);
|
||||||
|
if(DEBUG)printf("ContinuHigh retCode=%d\n",retCode);
|
||||||
|
if (retCode < 0) {
|
||||||
|
printf("ContinuHigh error\n");
|
||||||
|
close(fd);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set i<10 for more one check
|
||||||
|
for(i=0;i<1;i++) {
|
||||||
|
sleep(3);
|
||||||
|
readSize = read (fd, buf, 2);
|
||||||
|
if(DEBUG)printf("read readSize=%d %x %x\n",readSize,buf[0],buf[1]);
|
||||||
|
|
||||||
|
res = buf[0]*256+buf[1];
|
||||||
|
if(DEBUG)printf("res=%x\n",res);
|
||||||
|
lux = res / 1.2;
|
||||||
|
// printf("Lux=%d\n",lux);
|
||||||
|
printf("Brightness (Lux)\t%0.1f\n", ((double)lux));
|
||||||
|
}
|
||||||
|
|
||||||
|
retCode=i2c_smbus_write_byte(fd, PowerDown);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
exit (0);
|
||||||
|
}
|
|
@ -0,0 +1,212 @@
|
||||||
|
/*
|
||||||
|
Sample code for the BMP085
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <linux/i2c-dev.h>
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include "smbus.h"
|
||||||
|
|
||||||
|
#define BMP085_I2C_ADDRESS 0x77
|
||||||
|
|
||||||
|
const unsigned char BMP085_OVERSAMPLING_SETTING = 3;
|
||||||
|
|
||||||
|
// Calibration values - These are stored in the BMP085
|
||||||
|
short int ac1;
|
||||||
|
short int ac2;
|
||||||
|
short int ac3;
|
||||||
|
unsigned short int ac4;
|
||||||
|
unsigned short int ac5;
|
||||||
|
unsigned short int ac6;
|
||||||
|
short int b1;
|
||||||
|
short int b2;
|
||||||
|
short int mb;
|
||||||
|
short int mc;
|
||||||
|
short int md;
|
||||||
|
|
||||||
|
int b5;
|
||||||
|
|
||||||
|
unsigned int temperature, pressure;
|
||||||
|
|
||||||
|
|
||||||
|
// Open a connection to the bmp085
|
||||||
|
// Returns a file id
|
||||||
|
int bmp085_i2c_Begin()
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
char *fileName = "/dev/i2c-0";
|
||||||
|
|
||||||
|
// Open port for reading and writing
|
||||||
|
if ((fd = open(fileName, O_RDWR)) < 0)
|
||||||
|
exit(1);
|
||||||
|
|
||||||
|
// Set the port options and set the address of the device
|
||||||
|
if (ioctl(fd, I2C_SLAVE, BMP085_I2C_ADDRESS) < 0) {
|
||||||
|
close(fd);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read two words from the BMP085 and supply it as a 16 bit integer
|
||||||
|
__s32 bmp085_i2c_Read_Int(int fd, __u8 address)
|
||||||
|
{
|
||||||
|
__s32 res = i2c_smbus_read_word_data(fd, address);
|
||||||
|
if (res < 0) {
|
||||||
|
close(fd);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert result to 16 bits and swap bytes
|
||||||
|
res = ((res<<8) & 0xFF00) | ((res>>8) & 0xFF);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Write a byte to the BMP085
|
||||||
|
void bmp085_i2c_Write_Byte(int fd, __u8 address, __u8 value)
|
||||||
|
{
|
||||||
|
if (i2c_smbus_write_byte_data(fd, address, value) < 0) {
|
||||||
|
close(fd);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read a block of data BMP085
|
||||||
|
void bmp085_i2c_Read_Block(int fd, __u8 address, __u8 length, __u8 *values)
|
||||||
|
{
|
||||||
|
if(i2c_smbus_read_i2c_block_data(fd, address,length,values)<0) {
|
||||||
|
close(fd);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void bmp085_Calibration()
|
||||||
|
{
|
||||||
|
int fd = bmp085_i2c_Begin();
|
||||||
|
ac1 = bmp085_i2c_Read_Int(fd,0xAA);
|
||||||
|
ac2 = bmp085_i2c_Read_Int(fd,0xAC);
|
||||||
|
ac3 = bmp085_i2c_Read_Int(fd,0xAE);
|
||||||
|
ac4 = bmp085_i2c_Read_Int(fd,0xB0);
|
||||||
|
ac5 = bmp085_i2c_Read_Int(fd,0xB2);
|
||||||
|
ac6 = bmp085_i2c_Read_Int(fd,0xB4);
|
||||||
|
b1 = bmp085_i2c_Read_Int(fd,0xB6);
|
||||||
|
b2 = bmp085_i2c_Read_Int(fd,0xB8);
|
||||||
|
mb = bmp085_i2c_Read_Int(fd,0xBA);
|
||||||
|
mc = bmp085_i2c_Read_Int(fd,0xBC);
|
||||||
|
md = bmp085_i2c_Read_Int(fd,0xBE);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the uncompensated temperature value
|
||||||
|
unsigned int bmp085_ReadUT()
|
||||||
|
{
|
||||||
|
unsigned int ut = 0;
|
||||||
|
int fd = bmp085_i2c_Begin();
|
||||||
|
|
||||||
|
// Write 0x2E into Register 0xF4
|
||||||
|
// This requests a temperature reading
|
||||||
|
bmp085_i2c_Write_Byte(fd,0xF4,0x2E);
|
||||||
|
|
||||||
|
// Wait at least 4.5ms
|
||||||
|
usleep(5000);
|
||||||
|
|
||||||
|
// Read the two byte result from address 0xF6
|
||||||
|
ut = bmp085_i2c_Read_Int(fd,0xF6);
|
||||||
|
|
||||||
|
// Close the i2c file
|
||||||
|
close (fd);
|
||||||
|
|
||||||
|
return ut;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the uncompensated pressure value
|
||||||
|
unsigned int bmp085_ReadUP()
|
||||||
|
{
|
||||||
|
unsigned int up = 0;
|
||||||
|
int fd = bmp085_i2c_Begin();
|
||||||
|
|
||||||
|
// Write 0x34+(BMP085_OVERSAMPLING_SETTING<<6) into register 0xF4
|
||||||
|
// Request a pressure reading w/ oversampling setting
|
||||||
|
bmp085_i2c_Write_Byte(fd,0xF4,0x34 + (BMP085_OVERSAMPLING_SETTING<<6));
|
||||||
|
|
||||||
|
// Wait for conversion, delay time dependent on oversampling setting
|
||||||
|
usleep((2 + (3<<BMP085_OVERSAMPLING_SETTING)) * 1000);
|
||||||
|
|
||||||
|
// Read the three byte result from 0xF6
|
||||||
|
// 0xF6 = MSB, 0xF7 = LSB and 0xF8 = XLSB
|
||||||
|
__u8 values[3];
|
||||||
|
bmp085_i2c_Read_Block(fd, 0xF6, 3, values);
|
||||||
|
|
||||||
|
up = (((unsigned int) values[0] << 16) | ((unsigned int) values[1] << 8) | (unsigned int) values[2]) >> (8-BMP085_OVERSAMPLING_SETTING);
|
||||||
|
|
||||||
|
return up;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate pressure given uncalibrated pressure
|
||||||
|
// Value returned will be in units of XXXXX
|
||||||
|
unsigned int bmp085_GetPressure(unsigned int up)
|
||||||
|
{
|
||||||
|
int x1, x2, x3, b3, b6, p;
|
||||||
|
unsigned int b4, b7;
|
||||||
|
|
||||||
|
b6 = b5 - 4000;
|
||||||
|
// Calculate B3
|
||||||
|
x1 = (b2 * (b6 * b6)>>12)>>11;
|
||||||
|
x2 = (ac2 * b6)>>11;
|
||||||
|
x3 = x1 + x2;
|
||||||
|
b3 = (((((int)ac1)*4 + x3)<<BMP085_OVERSAMPLING_SETTING) + 2)>>2;
|
||||||
|
|
||||||
|
// Calculate B4
|
||||||
|
x1 = (ac3 * b6)>>13;
|
||||||
|
x2 = (b1 * ((b6 * b6)>>12))>>16;
|
||||||
|
x3 = ((x1 + x2) + 2)>>2;
|
||||||
|
b4 = (ac4 * (unsigned int)(x3 + 32768))>>15;
|
||||||
|
|
||||||
|
b7 = ((unsigned int)(up - b3) * (50000>>BMP085_OVERSAMPLING_SETTING));
|
||||||
|
if (b7 < 0x80000000)
|
||||||
|
p = (b7<<1)/b4;
|
||||||
|
else
|
||||||
|
p = (b7/b4)<<1;
|
||||||
|
|
||||||
|
x1 = (p>>8) * (p>>8);
|
||||||
|
x1 = (x1 * 3038)>>16;
|
||||||
|
x2 = (-7357 * p)>>16;
|
||||||
|
p += (x1 + x2 + 3791)>>4;
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate temperature given uncalibrated temperature
|
||||||
|
// Value returned will be in units of 0.1 deg C
|
||||||
|
unsigned int bmp085_GetTemperature(unsigned int ut)
|
||||||
|
{
|
||||||
|
int x1, x2;
|
||||||
|
|
||||||
|
x1 = (((int)ut - (int)ac6)*(int)ac5) >> 15;
|
||||||
|
x2 = ((int)mc << 11)/(x1 + md);
|
||||||
|
b5 = x1 + x2;
|
||||||
|
|
||||||
|
unsigned int result = ((b5 + 8)>>4);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
bmp085_Calibration();
|
||||||
|
temperature = bmp085_GetTemperature(bmp085_ReadUT());
|
||||||
|
pressure = bmp085_GetPressure(bmp085_ReadUP());
|
||||||
|
|
||||||
|
printf("Temperature (C)\t\t%0.1f\n", ((double)temperature)/10,0x00B0);
|
||||||
|
// printf("Pressure (hPa)\t%0.2f\n", ((double)pressure)/100);
|
||||||
|
//printf("Pressure (mmHg)\t%0.2f\n", ((double)pressure)/100*0.75006375541921);
|
||||||
|
printf("Pressure (mmHg)\t\t%0.2f\n", ((double)pressure)/100*0.750061683);
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,134 @@
|
||||||
|
/* Test DS1621 sur interface I2C GPIO Fonera (3/2008) */
|
||||||
|
/* Inspir de "Un bus i2c pour La Fonera" */
|
||||||
|
/* http://www.lefinnois.net/wp/index.php/2007/05/05/un-bus-i2c-pour-la-fonera/ */
|
||||||
|
|
||||||
|
/* Affichage de la t */
|
||||||
|
/* Par domos domos78<at>free<point>fr */
|
||||||
|
/* http://vesta.homelinux.net/ */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <linux/i2c-dev.h>
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
|
||||||
|
#define I2C_SLAVE 0x0703 // Change slave address
|
||||||
|
|
||||||
|
static int i2c_fd ;
|
||||||
|
int res ;
|
||||||
|
|
||||||
|
#define DEVICE "/dev/i2c-0"
|
||||||
|
#define ds1621_addr 0x9E >> 1 // 0x4f - Address (A0+A1+A2 to Vcc)
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------*/
|
||||||
|
/* Fonctions i2c */
|
||||||
|
/*------------------------------------------------------------------------------*/
|
||||||
|
void i2c_init()
|
||||||
|
{
|
||||||
|
if ((i2c_fd = open(DEVICE, O_RDWR)) < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Erreur ouverture port: %s (%d)\n", strerror(errno), errno);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void SelectSlave(unsigned char slaveaddr)
|
||||||
|
{
|
||||||
|
if (ioctl(i2c_fd, I2C_SLAVE, slaveaddr) < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Erreur selection esclave i2c: %s (%d)\n", strerror(errno), errno);
|
||||||
|
close ( i2c_fd ) ;
|
||||||
|
exit(EXIT_FAILURE) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------*/
|
||||||
|
/* Fonctions DS1621 */
|
||||||
|
/*------------------------------------------------------------------------------*/
|
||||||
|
int i2c_init_ds1621(unsigned char addr)
|
||||||
|
{
|
||||||
|
int res ;
|
||||||
|
char buff[10] ;
|
||||||
|
|
||||||
|
SelectSlave(addr) ;
|
||||||
|
buff[0] = 0xAC ;
|
||||||
|
buff[1] = 0x01 ;
|
||||||
|
res = write( i2c_fd, buff, 2 );
|
||||||
|
if ( res < 0 )
|
||||||
|
{
|
||||||
|
printf("Erreur init DS1621 addr 0x%x: '%s', Abandon programme !", addr, strerror(errno));
|
||||||
|
close ( i2c_fd );
|
||||||
|
exit(1) ;
|
||||||
|
}
|
||||||
|
/* start temperature conversion */
|
||||||
|
errno = 0 ;
|
||||||
|
buff[0] = 0xEE ;
|
||||||
|
write( i2c_fd, buff, 1 );
|
||||||
|
sleep(1) ;
|
||||||
|
return 1 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
double i2c_gettemp_ds1621(unsigned char addr)
|
||||||
|
{
|
||||||
|
int k, count, slope, temp;
|
||||||
|
char buff[10] ;
|
||||||
|
|
||||||
|
SelectSlave(addr) ;
|
||||||
|
/* stop conversion */
|
||||||
|
errno = 0 ;
|
||||||
|
buff[0] = 0x22 ;
|
||||||
|
|
||||||
|
if ( write( i2c_fd, buff, 1 ) < 0 ) return 255 ; // Write retourne -1 et strerror(errno))='Remote I/O error' si adr. i2c non connecte.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Temperature reading (1 Celsius degree precision) */
|
||||||
|
buff[0] = 0xAA ;
|
||||||
|
write( i2c_fd, buff, 1 );
|
||||||
|
read(i2c_fd, buff, 1) ;
|
||||||
|
temp = buff[0] ;
|
||||||
|
/* Counter reading (fraction of degree) ) */
|
||||||
|
buff[0] = 0xA8 ;
|
||||||
|
write( i2c_fd, buff, 1 );
|
||||||
|
read(i2c_fd, buff, 1) ;
|
||||||
|
count = buff[0] ;
|
||||||
|
/* slope reading */
|
||||||
|
buff[0] = 0xA9 ;
|
||||||
|
write( i2c_fd, buff, 1 );
|
||||||
|
read(i2c_fd, buff, 1) ;
|
||||||
|
slope = buff[0] ;
|
||||||
|
k = temp;
|
||||||
|
if (slope != 0)
|
||||||
|
{
|
||||||
|
k = temp*100-25+(100*(slope-count))/slope;
|
||||||
|
}
|
||||||
|
/* start temperature conversion */
|
||||||
|
buff[0] = 0xEE ;
|
||||||
|
write( i2c_fd, buff, 1 );
|
||||||
|
return (float)k/100 ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------*/
|
||||||
|
int main ( int argc, char ** argv )
|
||||||
|
{
|
||||||
|
// Init i2c.
|
||||||
|
i2c_init() ;
|
||||||
|
|
||||||
|
// Init ds1621.
|
||||||
|
i2c_init_ds1621(ds1621_addr) ;
|
||||||
|
|
||||||
|
// Affiche la t.
|
||||||
|
printf("%2.1f\n", i2c_gettemp_ds1621(ds1621_addr) ) ;
|
||||||
|
|
||||||
|
close ( i2c_fd );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -0,0 +1,400 @@
|
||||||
|
/*
|
||||||
|
* INA219 util - part of PowerCape by AndiceLabs
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 AndiceLabs admin@andicelabs.com http://andicelabs.com
|
||||||
|
* Copyright (C) 2014 Zig Fisher flyrouter@gmail.com http://zftlab.org
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* of the License, 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.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Example run and output:
|
||||||
|
*
|
||||||
|
* OpenWRT:~# ina219 -b 0 -i 60
|
||||||
|
*
|
||||||
|
* 22:49 12168mV 134.2mA
|
||||||
|
* 22:50 12168mV 239.9mA
|
||||||
|
* 22:51 12168mV 134.7mA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <endian.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <linux/i2c-dev.h>
|
||||||
|
|
||||||
|
#define CONFIG_REG 0
|
||||||
|
#define SHUNT_REG 1
|
||||||
|
#define BUS_REG 2
|
||||||
|
#define POWER_REG 3
|
||||||
|
#define CURRENT_REG 4
|
||||||
|
#define CALIBRATION_REG 5
|
||||||
|
|
||||||
|
#define AVR_ADDRESS 0x21
|
||||||
|
#define INA_ADDRESS 0x40
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
OP_DUMP,
|
||||||
|
OP_VOLTAGE,
|
||||||
|
OP_CURRENT,
|
||||||
|
OP_MONITOR,
|
||||||
|
OP_NONE
|
||||||
|
} op_type;
|
||||||
|
|
||||||
|
op_type operation = OP_DUMP;
|
||||||
|
|
||||||
|
int interval = 60;
|
||||||
|
int i2c_bus = 0;
|
||||||
|
int i2c_address = INA_ADDRESS;
|
||||||
|
int handle;
|
||||||
|
int whole_numbers = 0;
|
||||||
|
|
||||||
|
|
||||||
|
void msleep( int msecs )
|
||||||
|
{
|
||||||
|
usleep( msecs * 1000 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int i2c_read( void *buf, int len )
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if ( read( handle, buf, len ) != len )
|
||||||
|
{
|
||||||
|
printf( "I2C read failed: %s\n", strerror( errno ) );
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int i2c_write( void *buf, int len )
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if ( write( handle, buf, len ) != len )
|
||||||
|
{
|
||||||
|
printf( "I2C write failed: %s\n", strerror( errno ) );
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int register_read( unsigned char reg, unsigned short *data )
|
||||||
|
{
|
||||||
|
int rc = -1;
|
||||||
|
unsigned char bite[ 4 ];
|
||||||
|
|
||||||
|
bite[ 0 ] = reg;
|
||||||
|
if ( i2c_write( bite, 1 ) == 0 )
|
||||||
|
{
|
||||||
|
if ( i2c_read( bite, 2 ) == 0 )
|
||||||
|
{
|
||||||
|
*data = ( bite[ 0 ] << 8 ) | bite[ 1 ];
|
||||||
|
rc = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int register_write( unsigned char reg, unsigned short data )
|
||||||
|
{
|
||||||
|
int rc = -1;
|
||||||
|
unsigned char bite[ 4 ];
|
||||||
|
|
||||||
|
bite[ 0 ] = reg;
|
||||||
|
bite[ 1 ] = ( data >> 8 ) & 0xFF;
|
||||||
|
bite[ 2 ] = ( data & 0xFF );
|
||||||
|
|
||||||
|
if ( i2c_write( bite, 3 ) == 0 )
|
||||||
|
{
|
||||||
|
rc = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void show_usage( char *progname )
|
||||||
|
{
|
||||||
|
fprintf( stderr, "Usage: %s <mode> \n", progname );
|
||||||
|
fprintf( stderr, " Mode (required):\n" );
|
||||||
|
fprintf( stderr, " -h --help Show usage.\n" );
|
||||||
|
fprintf( stderr, " -i --interval Set interval for monitor mode.\n" );
|
||||||
|
fprintf( stderr, " -w --whole Show whole numbers only. Useful for scripts.\n" );
|
||||||
|
fprintf( stderr, " -v --voltage Show battery voltage in mV.\n" );
|
||||||
|
fprintf( stderr, " -c --current Show battery current in mA.\n" );
|
||||||
|
fprintf( stderr, " -a --address <addr> Override I2C address of INA219 from default of 0x%02X.\n", i2c_address );
|
||||||
|
fprintf( stderr, " -b --bus <i2c bus> Override I2C bus from default of %d.\n", i2c_bus );
|
||||||
|
exit( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void parse( int argc, char *argv[] )
|
||||||
|
{
|
||||||
|
while( 1 )
|
||||||
|
{
|
||||||
|
static const struct option lopts[] =
|
||||||
|
{
|
||||||
|
{ "address", 0, 0, 'a' },
|
||||||
|
{ "bus", 0, 0, 'b' },
|
||||||
|
{ "current", 0, 0, 'c' },
|
||||||
|
{ "help", 0, 0, 'h' },
|
||||||
|
{ "interval", 0, 0, 'i' },
|
||||||
|
{ "voltage", 0, 0, 'v' },
|
||||||
|
{ "whole", 0, 0, 'w' },
|
||||||
|
{ NULL, 0, 0, 0 },
|
||||||
|
};
|
||||||
|
int c;
|
||||||
|
|
||||||
|
c = getopt_long( argc, argv, "a:b:chi:vw", lopts, NULL );
|
||||||
|
|
||||||
|
if( c == -1 )
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch( c )
|
||||||
|
{
|
||||||
|
case 'a':
|
||||||
|
{
|
||||||
|
errno = 0;
|
||||||
|
i2c_address = (int)strtol( optarg, NULL, 0 );
|
||||||
|
if ( errno != 0 )
|
||||||
|
{
|
||||||
|
fprintf( stderr, "Unknown address parameter %s.\n", optarg );
|
||||||
|
exit( 1 );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'b':
|
||||||
|
{
|
||||||
|
errno = 0;
|
||||||
|
i2c_bus = (int)strtol( optarg, NULL, 0 );
|
||||||
|
if ( errno != 0 )
|
||||||
|
{
|
||||||
|
fprintf( stderr, "Unknown bus parameter %s.\n", optarg );
|
||||||
|
exit( 1 );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'c':
|
||||||
|
{
|
||||||
|
operation = OP_CURRENT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
case 'h':
|
||||||
|
{
|
||||||
|
operation = OP_NONE;
|
||||||
|
show_usage( argv[ 0 ] );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'i':
|
||||||
|
{
|
||||||
|
operation = OP_MONITOR;
|
||||||
|
interval = atoi( optarg );
|
||||||
|
if ( ( interval == 0 ) && ( errno != 0 ) )
|
||||||
|
{
|
||||||
|
fprintf( stderr, "Invalid interval value\n" );
|
||||||
|
exit( 1 );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'v':
|
||||||
|
{
|
||||||
|
operation = OP_VOLTAGE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'w':
|
||||||
|
{
|
||||||
|
whole_numbers = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int get_voltage( float *mv )
|
||||||
|
{
|
||||||
|
short bus;
|
||||||
|
|
||||||
|
if ( register_read( BUS_REG, (unsigned short*)&bus ) != 0 )
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*mv = ( float )( ( bus & 0xFFF8 ) >> 1 );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int get_current( float *ma )
|
||||||
|
{
|
||||||
|
short shunt;
|
||||||
|
|
||||||
|
if ( register_read( SHUNT_REG, &shunt ) != 0 )
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ma = (float)shunt / 10;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void show_current( void )
|
||||||
|
{
|
||||||
|
float ma;
|
||||||
|
|
||||||
|
if ( get_current( &ma ) )
|
||||||
|
{
|
||||||
|
fprintf( stderr, "Error reading current\n" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( whole_numbers )
|
||||||
|
{
|
||||||
|
printf( "%4.0f\n", ma );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf( "%04.1f\n", ma );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void show_voltage( void )
|
||||||
|
{
|
||||||
|
float mv;
|
||||||
|
|
||||||
|
if ( get_voltage( &mv ) )
|
||||||
|
{
|
||||||
|
fprintf( stderr, "Error reading voltage\n" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
printf( "%4.0f\n", mv );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void show_voltage_current( void )
|
||||||
|
{
|
||||||
|
float mv, ma;
|
||||||
|
|
||||||
|
if ( get_current( &ma ) || get_voltage( &mv ) )
|
||||||
|
{
|
||||||
|
fprintf( stderr, "Error reading voltage/current\n" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( whole_numbers )
|
||||||
|
{
|
||||||
|
printf( "%04.0fmV %4.0fmA\n", mv, ma );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf( "%04.0fmV %04.1fmA\n", mv, ma );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void monitor( void )
|
||||||
|
{
|
||||||
|
struct tm *tmptr;
|
||||||
|
time_t seconds;
|
||||||
|
|
||||||
|
while ( 1 )
|
||||||
|
{
|
||||||
|
seconds = time( NULL );
|
||||||
|
tmptr = localtime( &seconds );
|
||||||
|
printf( "%02d:%02d ", tmptr->tm_hour, tmptr->tm_min );
|
||||||
|
show_voltage_current();
|
||||||
|
sleep( interval );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main( int argc, char *argv[] )
|
||||||
|
{
|
||||||
|
char filename[ 20 ];
|
||||||
|
|
||||||
|
parse( argc, argv );
|
||||||
|
|
||||||
|
snprintf( filename, 19, "/dev/i2c-%d", i2c_bus );
|
||||||
|
handle = open( filename, O_RDWR );
|
||||||
|
if ( handle < 0 )
|
||||||
|
{
|
||||||
|
fprintf( stderr, "Error opening bus %d: %s\n", i2c_bus, strerror( errno ) );
|
||||||
|
exit( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ioctl( handle, I2C_SLAVE, i2c_address ) < 0 )
|
||||||
|
{
|
||||||
|
fprintf( stderr, "Error setting address %02X: %s\n", i2c_address, strerror( errno ) );
|
||||||
|
exit( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ( operation )
|
||||||
|
{
|
||||||
|
case OP_DUMP:
|
||||||
|
{
|
||||||
|
show_voltage_current();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case OP_VOLTAGE:
|
||||||
|
{
|
||||||
|
show_voltage();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case OP_CURRENT:
|
||||||
|
{
|
||||||
|
show_current();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case OP_MONITOR:
|
||||||
|
{
|
||||||
|
monitor();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
case OP_NONE:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close( handle );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
LM75_address.c
|
||||||
|
--------------
|
||||||
|
1) set the i2c address of the LM75
|
||||||
|
* R/W pulse at end of address byte not included in address 1-0-0-1-A2-A1-A0
|
||||||
|
* example - all lines to 0V - 1001000 = decimal 72
|
||||||
|
2) calculate the temperature
|
||||||
|
3) print it
|
||||||
|
usage :- type (without the < >)
|
||||||
|
<LM75_address><space><address as decimal>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <linux/i2c-dev.h>
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include "smbus.h"
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
int address; /* i2c bus address */
|
||||||
|
|
||||||
|
if (argc != 2) /* report error if we are not getting just 1 input after the program name */
|
||||||
|
{
|
||||||
|
printf("Error. usage: %s i2c_chip_address\n", argv[0]);
|
||||||
|
}
|
||||||
|
address = atoi(argv[1]); /* address is the first number after the program name */
|
||||||
|
|
||||||
|
|
||||||
|
int f = open("/dev/i2c-0",O_RDWR);
|
||||||
|
char buf[2];
|
||||||
|
if (f>0) {
|
||||||
|
ioctl(f,I2C_SLAVE,address);
|
||||||
|
if (-1 == read(f,buf,2)) {
|
||||||
|
printf("read error.\n");
|
||||||
|
} else { /* calculate the temperature*/
|
||||||
|
int temp = buf[0]*256+buf[1];
|
||||||
|
temp >>=7;
|
||||||
|
if (temp>512)
|
||||||
|
temp &= -1;
|
||||||
|
printf("Temperature (C)\t\t%g\n", (float)temp/2.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return close(f);
|
||||||
|
}
|
|
@ -0,0 +1,110 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <linux/i2c-dev.h>
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
|
||||||
|
#include <unistd.h> /* add by paulerr*/
|
||||||
|
|
||||||
|
|
||||||
|
#define CHIP "/dev/i2c-0"
|
||||||
|
#define CHIP_ADDR 0x40 //HTU21D地址
|
||||||
|
#define READ_TEMP 0XE3 //温度转换命令
|
||||||
|
#define READ_HUM 0XE5 //湿度转换命令
|
||||||
|
|
||||||
|
/* More info: https://github.com/kingmacth/Openwet-SDK/tree/master/package/HTU21D */
|
||||||
|
|
||||||
|
unsigned char HTU21D_Check_CRC(unsigned short int message_from_sensor,unsigned char check_value_from_sensor);
|
||||||
|
|
||||||
|
int main()
|
||||||
|
|
||||||
|
{
|
||||||
|
printf("hello,this is HTU21D tester \n");
|
||||||
|
int fd =open(CHIP, O_RDWR);
|
||||||
|
if (fd< 0) {
|
||||||
|
printf("open"CHIP"failed \n");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ioctl(fd,I2C_SLAVE_FORCE, CHIP_ADDR) < 0) { /*设置芯片地址 */
|
||||||
|
printf("oictl:setslave address failed\n");
|
||||||
|
goto close;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct i2c_msg msg;
|
||||||
|
|
||||||
|
unsigned char rddata[3];
|
||||||
|
unsigned char rdaddr[2] = {0x10, 0}; /* 将要读取的数据在芯片中的偏移量 */
|
||||||
|
unsigned char TempAddr[2] = {0xe3, 0}; /* 发送E3读取温度 */
|
||||||
|
unsigned char HumAddr[2] = {0xE5, 0}; /* 发送E5读取湿度 */
|
||||||
|
unsigned short int tmp_dat,CRC_Result;
|
||||||
|
float Temp,Hum;
|
||||||
|
/*printf("inputa char you want to write to E2PROM\n");
|
||||||
|
wrbuf[2]= getchar();
|
||||||
|
printf("writereturn:%d, write data:%x\n", write(fd, wrbuf, 1), wrbuf[2]);
|
||||||
|
sleep(5);*/
|
||||||
|
//printf("Read temp!\n",write(fd, TempAddr, 1)); /* 开启温度转换 */
|
||||||
|
write(fd, TempAddr, 1);
|
||||||
|
usleep(100000);
|
||||||
|
read(fd, &rddata, 3); //读取两字节温度一字节校验
|
||||||
|
|
||||||
|
tmp_dat=rddata[0];
|
||||||
|
tmp_dat=tmp_dat<<8;
|
||||||
|
tmp_dat=tmp_dat+rddata[1];
|
||||||
|
//printf("rddata:%x%02x,%x\n", rddata[0], rddata[1],rddata[2]);
|
||||||
|
CRC_Result=HTU21D_Check_CRC(tmp_dat,rddata[2]);
|
||||||
|
//printf("CRC=%x,%x\n",CRC_Result ,tmp_dat);//CRC校验
|
||||||
|
if(CRC_Result==0)
|
||||||
|
{
|
||||||
|
Temp=(tmp_dat*175.72)/65536-46.85;
|
||||||
|
printf("Temp=%.2f\n",Temp);
|
||||||
|
}
|
||||||
|
//printf("Read hum!\n",write(fd, HumAddr, 1)); /* 开启湿度转换 */
|
||||||
|
write(fd, HumAddr, 1);
|
||||||
|
usleep(100000);
|
||||||
|
read(fd, &rddata, 3); //读取两字节湿度一字节校验
|
||||||
|
|
||||||
|
tmp_dat=rddata[0];
|
||||||
|
tmp_dat=tmp_dat<<8;
|
||||||
|
tmp_dat=tmp_dat+rddata[1];
|
||||||
|
//printf("rddata:%x%02x,%x\n", rddata[0], rddata[1],rddata[2]);
|
||||||
|
CRC_Result=HTU21D_Check_CRC(tmp_dat,rddata[2]);
|
||||||
|
//printf("CRC=%x,%x\n",CRC_Result ,tmp_dat);//CRC校验
|
||||||
|
if(CRC_Result==0)
|
||||||
|
{
|
||||||
|
Temp=(tmp_dat*125)/65536-6;
|
||||||
|
printf("Hum=%.2f%%RH\n",Temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
close:
|
||||||
|
close(fd);
|
||||||
|
exit:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//**************************************************************************************************************
|
||||||
|
//两个参数一个是传感器的源数据,另一个是传感器得出的CRC校验值
|
||||||
|
//如果校验通过返回0,不通过返回非0
|
||||||
|
//From: http://www.nongnu.org/avr-libc/user-manual/group__util__crc.html
|
||||||
|
//POLYNOMIAL = 0x0131 = x^8 + x^5 + x^4 + 1 : http://en.wikipedia.org/wiki/Computation_of_cyclic_redundancy_checks
|
||||||
|
#define SHIFTED_DIVISOR 0x988000 //This is the 0x0131 polynomial shifted to farthest left of three bytes
|
||||||
|
//**************************************************************************************************************
|
||||||
|
unsigned char HTU21D_Check_CRC(unsigned short int message_from_sensor,unsigned char check_value_from_sensor)
|
||||||
|
{
|
||||||
|
unsigned char i;
|
||||||
|
//Test cases from datasheet:
|
||||||
|
//message = 0xDC, checkvalue is 0x79
|
||||||
|
//message = 0x683A, checkvalue is 0x7C
|
||||||
|
//message = 0x4E85, checkvalue is 0x6B
|
||||||
|
unsigned int remainder = (unsigned int)message_from_sensor << 8; //Pad with 8 bits because we have to add in the check value
|
||||||
|
unsigned int divsor = (unsigned int)SHIFTED_DIVISOR;
|
||||||
|
remainder |= check_value_from_sensor; //Add on the check value
|
||||||
|
for (i = 0 ; i < 16 ; i++) //Operate on only 16 positions of max 24. The remaining 8 are our remainder and should be zero when we're done.
|
||||||
|
{
|
||||||
|
if( remainder & (unsigned int)1<<(23 - i) ) //Check if there is a one in the left position
|
||||||
|
remainder ^= divsor;
|
||||||
|
divsor>>=1;//Rotatethedivsormax16timessothatwehave8bitsleftofaremainder
|
||||||
|
}
|
||||||
|
return(unsigned char)remainder;
|
||||||
|
}
|
|
@ -0,0 +1,228 @@
|
||||||
|
/*
|
||||||
|
smbus.c - SMBus level access helper functions
|
||||||
|
|
||||||
|
Copyright (C) 1995-97 Simon G. Vogl
|
||||||
|
Copyright (C) 1998-99 Frodo Looijaard <frodol@dds.nl>
|
||||||
|
Copyright (C) 2012 Jean Delvare <khali@linux-fr.org>
|
||||||
|
|
||||||
|
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 of the License, 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, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include "smbus.h" // NB: Path changed!
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
#include <linux/i2c-dev.h>
|
||||||
|
|
||||||
|
//NB: Added by John Burns
|
||||||
|
#ifndef NULL
|
||||||
|
#define NULL 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Compatibility defines */
|
||||||
|
#ifndef I2C_SMBUS_I2C_BLOCK_BROKEN
|
||||||
|
#define I2C_SMBUS_I2C_BLOCK_BROKEN I2C_SMBUS_I2C_BLOCK_DATA
|
||||||
|
#endif
|
||||||
|
#ifndef I2C_FUNC_SMBUS_PEC
|
||||||
|
#define I2C_FUNC_SMBUS_PEC I2C_FUNC_SMBUS_HWPEC_CALC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
__s32 i2c_smbus_access(int file, char read_write, __u8 command,
|
||||||
|
int size, union i2c_smbus_data *data)
|
||||||
|
{
|
||||||
|
struct i2c_smbus_ioctl_data args;
|
||||||
|
__s32 err;
|
||||||
|
|
||||||
|
args.read_write = read_write;
|
||||||
|
args.command = command;
|
||||||
|
args.size = size;
|
||||||
|
args.data = data;
|
||||||
|
|
||||||
|
err = ioctl(file, I2C_SMBUS, &args);
|
||||||
|
if (err == -1)
|
||||||
|
err = -errno;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
__s32 i2c_smbus_write_quick(int file, __u8 value)
|
||||||
|
{
|
||||||
|
return i2c_smbus_access(file, value, 0, I2C_SMBUS_QUICK, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
__s32 i2c_smbus_read_byte(int file)
|
||||||
|
{
|
||||||
|
union i2c_smbus_data data;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = i2c_smbus_access(file, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, &data);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
return 0x0FF & data.byte;
|
||||||
|
}
|
||||||
|
|
||||||
|
__s32 i2c_smbus_write_byte(int file, __u8 value)
|
||||||
|
{
|
||||||
|
return i2c_smbus_access(file, I2C_SMBUS_WRITE, value,
|
||||||
|
I2C_SMBUS_BYTE, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
__s32 i2c_smbus_read_byte_data(int file, __u8 command)
|
||||||
|
{
|
||||||
|
union i2c_smbus_data data;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = i2c_smbus_access(file, I2C_SMBUS_READ, command,
|
||||||
|
I2C_SMBUS_BYTE_DATA, &data);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
return 0x0FF & data.byte;
|
||||||
|
}
|
||||||
|
|
||||||
|
__s32 i2c_smbus_write_byte_data(int file, __u8 command, __u8 value)
|
||||||
|
{
|
||||||
|
union i2c_smbus_data data;
|
||||||
|
data.byte = value;
|
||||||
|
return i2c_smbus_access(file, I2C_SMBUS_WRITE, command,
|
||||||
|
I2C_SMBUS_BYTE_DATA, &data);
|
||||||
|
}
|
||||||
|
|
||||||
|
__s32 i2c_smbus_read_word_data(int file, __u8 command)
|
||||||
|
{
|
||||||
|
union i2c_smbus_data data;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = i2c_smbus_access(file, I2C_SMBUS_READ, command,
|
||||||
|
I2C_SMBUS_WORD_DATA, &data);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
return 0x0FFFF & data.word;
|
||||||
|
}
|
||||||
|
|
||||||
|
__s32 i2c_smbus_write_word_data(int file, __u8 command, __u16 value)
|
||||||
|
{
|
||||||
|
union i2c_smbus_data data;
|
||||||
|
data.word = value;
|
||||||
|
return i2c_smbus_access(file, I2C_SMBUS_WRITE, command,
|
||||||
|
I2C_SMBUS_WORD_DATA, &data);
|
||||||
|
}
|
||||||
|
|
||||||
|
__s32 i2c_smbus_process_call(int file, __u8 command, __u16 value)
|
||||||
|
{
|
||||||
|
union i2c_smbus_data data;
|
||||||
|
data.word = value;
|
||||||
|
if (i2c_smbus_access(file, I2C_SMBUS_WRITE, command,
|
||||||
|
I2C_SMBUS_PROC_CALL, &data))
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
return 0x0FFFF & data.word;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns the number of read bytes */
|
||||||
|
__s32 i2c_smbus_read_block_data(int file, __u8 command, __u8 *values)
|
||||||
|
{
|
||||||
|
union i2c_smbus_data data;
|
||||||
|
int i, err;
|
||||||
|
|
||||||
|
err = i2c_smbus_access(file, I2C_SMBUS_READ, command,
|
||||||
|
I2C_SMBUS_BLOCK_DATA, &data);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
for (i = 1; i <= data.block[0]; i++)
|
||||||
|
values[i-1] = data.block[i];
|
||||||
|
return data.block[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
__s32 i2c_smbus_write_block_data(int file, __u8 command, __u8 length,
|
||||||
|
const __u8 *values)
|
||||||
|
{
|
||||||
|
union i2c_smbus_data data;
|
||||||
|
int i;
|
||||||
|
if (length > I2C_SMBUS_BLOCK_MAX)
|
||||||
|
length = I2C_SMBUS_BLOCK_MAX;
|
||||||
|
for (i = 1; i <= length; i++)
|
||||||
|
data.block[i] = values[i-1];
|
||||||
|
data.block[0] = length;
|
||||||
|
return i2c_smbus_access(file, I2C_SMBUS_WRITE, command,
|
||||||
|
I2C_SMBUS_BLOCK_DATA, &data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns the number of read bytes */
|
||||||
|
/* Until kernel 2.6.22, the length is hardcoded to 32 bytes. If you
|
||||||
|
ask for less than 32 bytes, your code will only work with kernels
|
||||||
|
2.6.23 and later. */
|
||||||
|
__s32 i2c_smbus_read_i2c_block_data(int file, __u8 command, __u8 length,
|
||||||
|
__u8 *values)
|
||||||
|
{
|
||||||
|
union i2c_smbus_data data;
|
||||||
|
int i, err;
|
||||||
|
|
||||||
|
if (length > I2C_SMBUS_BLOCK_MAX)
|
||||||
|
length = I2C_SMBUS_BLOCK_MAX;
|
||||||
|
data.block[0] = length;
|
||||||
|
|
||||||
|
err = i2c_smbus_access(file, I2C_SMBUS_READ, command,
|
||||||
|
length == 32 ? I2C_SMBUS_I2C_BLOCK_BROKEN :
|
||||||
|
I2C_SMBUS_I2C_BLOCK_DATA, &data);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
for (i = 1; i <= data.block[0]; i++)
|
||||||
|
values[i-1] = data.block[i];
|
||||||
|
return data.block[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
__s32 i2c_smbus_write_i2c_block_data(int file, __u8 command, __u8 length,
|
||||||
|
const __u8 *values)
|
||||||
|
{
|
||||||
|
union i2c_smbus_data data;
|
||||||
|
int i;
|
||||||
|
if (length > I2C_SMBUS_BLOCK_MAX)
|
||||||
|
length = I2C_SMBUS_BLOCK_MAX;
|
||||||
|
for (i = 1; i <= length; i++)
|
||||||
|
data.block[i] = values[i-1];
|
||||||
|
data.block[0] = length;
|
||||||
|
return i2c_smbus_access(file, I2C_SMBUS_WRITE, command,
|
||||||
|
I2C_SMBUS_I2C_BLOCK_BROKEN, &data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns the number of read bytes */
|
||||||
|
__s32 i2c_smbus_block_process_call(int file, __u8 command, __u8 length,
|
||||||
|
__u8 *values)
|
||||||
|
{
|
||||||
|
union i2c_smbus_data data;
|
||||||
|
int i, err;
|
||||||
|
|
||||||
|
if (length > I2C_SMBUS_BLOCK_MAX)
|
||||||
|
length = I2C_SMBUS_BLOCK_MAX;
|
||||||
|
for (i = 1; i <= length; i++)
|
||||||
|
data.block[i] = values[i-1];
|
||||||
|
data.block[0] = length;
|
||||||
|
|
||||||
|
err = i2c_smbus_access(file, I2C_SMBUS_WRITE, command,
|
||||||
|
I2C_SMBUS_BLOCK_PROC_CALL, &data);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
for (i = 1; i <= data.block[0]; i++)
|
||||||
|
values[i-1] = data.block[i];
|
||||||
|
return data.block[0];
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
smbus.h - SMBus level access helper functions
|
||||||
|
|
||||||
|
Copyright (C) 1995-97 Simon G. Vogl
|
||||||
|
Copyright (C) 1998-99 Frodo Looijaard <frodol@dds.nl>
|
||||||
|
|
||||||
|
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 of the License, 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, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LIB_I2C_SMBUS_H
|
||||||
|
#define LIB_I2C_SMBUS_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
|
||||||
|
extern __s32 i2c_smbus_access(int file, char read_write, __u8 command,
|
||||||
|
int size, union i2c_smbus_data *data);
|
||||||
|
|
||||||
|
extern __s32 i2c_smbus_write_quick(int file, __u8 value);
|
||||||
|
extern __s32 i2c_smbus_read_byte(int file);
|
||||||
|
extern __s32 i2c_smbus_write_byte(int file, __u8 value);
|
||||||
|
extern __s32 i2c_smbus_read_byte_data(int file, __u8 command);
|
||||||
|
extern __s32 i2c_smbus_write_byte_data(int file, __u8 command, __u8 value);
|
||||||
|
extern __s32 i2c_smbus_read_word_data(int file, __u8 command);
|
||||||
|
extern __s32 i2c_smbus_write_word_data(int file, __u8 command, __u16 value);
|
||||||
|
extern __s32 i2c_smbus_process_call(int file, __u8 command, __u16 value);
|
||||||
|
|
||||||
|
/* Returns the number of read bytes */
|
||||||
|
extern __s32 i2c_smbus_read_block_data(int file, __u8 command, __u8 *values);
|
||||||
|
extern __s32 i2c_smbus_write_block_data(int file, __u8 command, __u8 length,
|
||||||
|
const __u8 *values);
|
||||||
|
|
||||||
|
/* Returns the number of read bytes */
|
||||||
|
/* Until kernel 2.6.22, the length is hardcoded to 32 bytes. If you
|
||||||
|
ask for less than 32 bytes, your code will only work with kernels
|
||||||
|
2.6.23 and later. */
|
||||||
|
extern __s32 i2c_smbus_read_i2c_block_data(int file, __u8 command, __u8 length,
|
||||||
|
__u8 *values);
|
||||||
|
extern __s32 i2c_smbus_write_i2c_block_data(int file, __u8 command, __u8 length,
|
||||||
|
const __u8 *values);
|
||||||
|
|
||||||
|
/* Returns the number of read bytes */
|
||||||
|
extern __s32 i2c_smbus_block_process_call(int file, __u8 command, __u8 length,
|
||||||
|
__u8 *values);
|
||||||
|
|
||||||
|
#endif /* LIB_I2C_SMBUS_H */
|
|
@ -0,0 +1,112 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
unsigned long parse_int (char *str);
|
||||||
|
|
||||||
|
void dumphex(const void* data, size_t size) {
|
||||||
|
char ascii[17];
|
||||||
|
size_t i, j;
|
||||||
|
ascii[16] = '\0';
|
||||||
|
for (i = 0; i < size; ++i) {
|
||||||
|
printf("%02X ", ((unsigned char*)data)[i]);
|
||||||
|
if (((unsigned char*)data)[i] >= ' ' && ((unsigned char*)data)[i] <= '~') {
|
||||||
|
ascii[i % 16] = ((unsigned char*)data)[i];
|
||||||
|
} else {
|
||||||
|
ascii[i % 16] = '.';
|
||||||
|
}
|
||||||
|
if ((i+1) % 8 == 0 || i+1 == size) {
|
||||||
|
printf(" ");
|
||||||
|
if ((i+1) % 16 == 0) {
|
||||||
|
printf("| %s \n", ascii);
|
||||||
|
} else if (i+1 == size) {
|
||||||
|
ascii[(i+1) % 16] = '\0';
|
||||||
|
if ((i+1) % 16 <= 8) {
|
||||||
|
printf(" ");
|
||||||
|
}
|
||||||
|
for (j = (i+1) % 16; j < 16; ++j) {
|
||||||
|
printf(" ");
|
||||||
|
}
|
||||||
|
printf("| %s \n", ascii);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main (int argc, char *argv[]) {
|
||||||
|
unsigned long addr, length;
|
||||||
|
|
||||||
|
int devmem;
|
||||||
|
void *mapping;
|
||||||
|
|
||||||
|
long page_size;
|
||||||
|
off_t map_base, extra_bytes;
|
||||||
|
|
||||||
|
char *buf;
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
|
if (argc != 3) {
|
||||||
|
fprintf(stderr, "Usage: %s ADDR LENGTH\n", argv[0]);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = parse_int(argv[1]);
|
||||||
|
length = parse_int(argv[2]);
|
||||||
|
|
||||||
|
devmem = open("/dev/mem", O_RDONLY);
|
||||||
|
if (devmem == -1) {
|
||||||
|
perror("Could not open /dev/mem");
|
||||||
|
goto open_fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
page_size = sysconf(_SC_PAGE_SIZE);
|
||||||
|
map_base = addr & ~(page_size - 1);
|
||||||
|
extra_bytes = addr - map_base;
|
||||||
|
|
||||||
|
mapping = mmap(NULL, length + extra_bytes, PROT_READ, MAP_SHARED,
|
||||||
|
devmem, map_base);
|
||||||
|
if (mapping == MAP_FAILED) {
|
||||||
|
perror("Could not map memory");
|
||||||
|
goto map_fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = malloc(length);
|
||||||
|
if (buf == NULL) {
|
||||||
|
fprintf(stderr, "Failed to allocate memory\n");
|
||||||
|
goto alloc_fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buf, (char *)mapping + extra_bytes, length);
|
||||||
|
|
||||||
|
dumphex(buf,length);
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
|
||||||
|
alloc_fail:
|
||||||
|
munmap(mapping, length + extra_bytes);
|
||||||
|
|
||||||
|
map_fail:
|
||||||
|
close(devmem);
|
||||||
|
|
||||||
|
open_fail:
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long parse_int (char *str) {
|
||||||
|
long long result;
|
||||||
|
char *endptr;
|
||||||
|
|
||||||
|
result = strtoll(str, &endptr, 0);
|
||||||
|
if (str == '\0' || *endptr != '\0') {
|
||||||
|
fprintf(stderr, "\"%s\" is not a valid number\n", str);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (unsigned long)result;
|
||||||
|
}
|
Loading…
Reference in New Issue