mirror of https://github.com/OpenIPC/firmware.git
Add i2c-telemetry, Fix hisi_gpio, Add memdump, Add Novatek profiles
parent
9431f437d5
commit
d3486717eb
.github/workflows
br-ext-chip-hisilicon
package
hisi_gpio_scanner
br-ext-chip-sigmastar/board/infinity6b0/kernel
|
@ -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/fwprintenv-ng/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/ipctool/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_FWPRINTENV_NG=y
|
||||
# BR2_PACKAGE_HASERL is not set
|
||||
BR2_PACKAGE_HISI_GPIO_SCANNER=y
|
||||
BR2_PACKAGE_HISI_GPIO=y
|
||||
BR2_PACKAGE_HISILICON_OSDRV4=y
|
||||
BR2_PACKAGE_IPCTOOL=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_FWPRINTENV_NG=y
|
||||
#BR2_PACKAGE_HASERL is not set
|
||||
BR2_PACKAGE_HISI_GPIO_SCANNER=y
|
||||
BR2_PACKAGE_HISI_GPIO=y
|
||||
BR2_PACKAGE_HISILICON_OSDRV4=y
|
||||
BR2_PACKAGE_IPCTOOL=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_FWPRINTENV_NG=y
|
||||
# BR2_PACKAGE_HASERL is not set
|
||||
BR2_PACKAGE_HISI_GPIO_SCANNER=y
|
||||
BR2_PACKAGE_HISI_GPIO=y
|
||||
BR2_PACKAGE_HISILICON_OSDRV4=y
|
||||
BR2_PACKAGE_IPCTOOL=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_FWPRINTENV_NG=y
|
||||
# BR2_PACKAGE_HASERL is not set
|
||||
BR2_PACKAGE_HISI_GPIO_SCANNER=y
|
||||
BR2_PACKAGE_HISI_GPIO=y
|
||||
BR2_PACKAGE_HISILICON_OSDRV4=y
|
||||
BR2_PACKAGE_IPCTOOL=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_FWPRINTENV_NG=y
|
||||
# BR2_PACKAGE_HASERL is not set
|
||||
BR2_PACKAGE_HISI_GPIO_SCANNER=y
|
||||
BR2_PACKAGE_HISI_GPIO=y
|
||||
BR2_PACKAGE_HISILICON_OSDRV4=y
|
||||
BR2_PACKAGE_IPCTOOL=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_FWPRINTENV_NG=y
|
||||
# BR2_PACKAGE_HASERL is not set
|
||||
BR2_PACKAGE_HISI_GPIO_SCANNER=y
|
||||
BR2_PACKAGE_HISI_GPIO=y
|
||||
BR2_PACKAGE_HISILICON_OSDRV4=y
|
||||
BR2_PACKAGE_IPCTOOL=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/gdbserver-lite/gdbserver-lite.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/ipctool/ipctool.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