Add i2c-telemetry, Fix hisi_gpio, Add memdump, Add Novatek profiles

pull/33/head
Igor Zalatov 2021-07-01 19:51:29 +03:00
parent 9431f437d5
commit d3486717eb
28 changed files with 5028 additions and 36 deletions

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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))

View File

@ -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;
}
//************************************************************
//************************************************************
//************************************************************

View File

@ -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

View File

@ -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))

View File

@ -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));
}
}

View File

@ -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( &current, 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;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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 );
}
/*------------------------------------------------------------------------------*/

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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];
}

View File

@ -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 */

View File

@ -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;
}