Skip to content

Commit 4d53028

Browse files
committed
Added HAT info tool
1 parent 0ea92b9 commit 4d53028

File tree

2 files changed

+141
-0
lines changed

2 files changed

+141
-0
lines changed

linux/hatinfo.c

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
//
2+
// Simple program to display the info of the attached RPI HAT
3+
// This info is stored in an I2C EEPROM attached to pins 27 & 28
4+
// of the 40 pin RPI GPIO header.
5+
//
6+
// Info about the physical, electrical and software specifications
7+
// of the RPI HAT standard are defined here:
8+
// https://github.com/raspberrypi/hats/blob/master/eeprom-format.md
9+
//
10+
// Copyright (c) 2021 BitBank Software, Inc.
11+
// Written by Larry Bank
12+
13+
// Project started 11/07/2021
14+
//
15+
// This program is free software: you can redistribute it and/or modify
16+
// it under the terms of the GNU General Public License as published by
17+
// the Free Software Foundation, either version 3 of the License, or
18+
// (at your option) any later version.
19+
//
20+
// This program is distributed in the hope that it will be useful,
21+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
22+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23+
// GNU General Public License for more details.
24+
//
25+
// You should have received a copy of the GNU General Public License
26+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
27+
//
28+
// Uses my Bit Bang I2C library. You can find it here:
29+
// https://github.com/bitbank2/BitBang_I2C
30+
#include <stdlib.h>
31+
#include <string.h>
32+
#include <stdio.h>
33+
#include <stdint.h>
34+
#include <inttypes.h>
35+
#include <BitBang_I2C.h>
36+
#include <pigpio.h>
37+
38+
BBI2C bbi2c;
39+
#define SDA_ID 27
40+
#define SCL_ID 28
41+
// Fixed address of all HAT EEPROM chips
42+
#define EEPROM_ADDR 0x50
43+
//
44+
// Read a block of 32 bytes at the given address
45+
// or from the last read address if iAddr == -1
46+
//
47+
int eeReadBlock(int iAddr, unsigned char *pData)
48+
{
49+
unsigned char ucTemp[4];
50+
int rc;
51+
52+
if (iAddr != -1) // send the address
53+
{
54+
ucTemp[0] = (unsigned char)(iAddr >> 8);
55+
ucTemp[1] = (unsigned char)iAddr;
56+
rc = I2CWrite(&bbi2c, EEPROM_ADDR, ucTemp, 2);
57+
} // otherwise read from the last address and increment
58+
rc = I2CRead(&bbi2c, EEPROM_ADDR, pData, 32);
59+
return (rc == 32);
60+
} /* eeReadBlock() */
61+
62+
const char *szTypes[] = {"invalid", "vendor info", "GPIO map", "Linux device tree blob", "manufacturer custom data", "reserved", "invalid"};
63+
64+
int main(int argc, char **argv)
65+
{
66+
int i, iAtoms, iLen, iOff;
67+
uint8_t ucHAT[256], ucTemp[256]; // read some of the HAT info here
68+
69+
memset(&bbi2c, 0, sizeof(bbi2c));
70+
bbi2c.bWire = 0; // use bit bang, not wire library
71+
bbi2c.iSDA = SDA_ID;
72+
bbi2c.iSCL = SCL_ID;
73+
I2CInit(&bbi2c, 100000L);
74+
// Read 256 bytes of the HAT data starting at offset 0
75+
for (i=0; i<256; i+=32) {
76+
eeReadBlock(i, &ucHAT[i]);
77+
}
78+
// Print signature
79+
memcpy(ucTemp, ucHAT, 4);
80+
ucTemp[4] = 0;
81+
printf("EEPROM Header Info:\n");
82+
printf("signature: %s\n", ucHAT);
83+
printf("version: 0x%02x\n", ucHAT[4]);
84+
iAtoms = ucHAT[6];
85+
printf("total atoms: %d\n", iAtoms);
86+
iLen = *(uint32_t *)&ucHAT[8];
87+
printf("total length: %d bytes\n", iLen);
88+
// Display info for each Atom
89+
iOff = 12; // starting offset of first Atom
90+
for (i=0; i<iAtoms; i++) {
91+
uint32_t iType, iSize;
92+
int j, iPins, vslen, pslen;
93+
iType = *(uint16_t *)&ucHAT[iOff];
94+
if (iType > 5 && iType < 0xffff) iType = 5; // reserved
95+
if (iType == 0xffff) iType = 0; // invalid
96+
iSize = *(uint32_t *)&ucHAT[iOff+4];
97+
printf("Atom Type: 0x%04x (%s)\n",iType, szTypes[iType]);
98+
printf("Atom Size: %d bytes\n",iSize);
99+
if (iType == 0x0001) { // vendor info
100+
printf("** Vendor Info **\n");
101+
printf(" UUID: %08x%08x%08x%08x\n", *(uint32_t *)&ucHAT[iOff+8], *(uint32_t *)&ucHAT[iOff+12], *(uint32_t *)&ucHAT[iOff+16], *(uint32_t *)&ucHAT[iOff+20]);
102+
printf(" Product ID: %d\n", *(uint16_t *)&ucHAT[iOff+24]);
103+
printf(" Product Ver: %d\n", *(uint16_t *)&ucHAT[iOff+26]);
104+
vslen = ucHAT[iOff+28]; // vendor name string length
105+
pslen = ucHAT[iOff+29]; // vendor product string length
106+
memcpy(ucTemp, &ucHAT[iOff+30], vslen);
107+
ucTemp[vslen] = 0;
108+
printf(" Vendor: %s\n", ucTemp);
109+
memcpy(ucTemp, &ucHAT[iOff+30+vslen], pslen);
110+
ucTemp[pslen] = 0;
111+
printf(" Product: %s\n", ucTemp);
112+
} else if (iType == 0x0002) { // GPIO map
113+
printf("** GPIO Map **\n");
114+
printf(" GPIO (BCM #) pins used:\n");
115+
iPins = 0;
116+
for (j=0; j<28; j++) {
117+
if (ucHAT[iOff+10+j] & 0x80) { // bit 7 indicates pin is used
118+
printf("%02d,",ucHAT[iOff+10+j]);
119+
iPins++;
120+
}
121+
}
122+
printf("\n %d pins defined\n", iPins);
123+
}
124+
iOff += iSize + 8;
125+
}
126+
printf("** End of Atom list **\n");
127+
return 0;
128+
}

linux/make_hatinfo

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CFLAGS=-c -Wall -O2
2+
LIBS = -lBitBang_I2C -lpigpio
3+
4+
all: hatinfo
5+
6+
hatinfo: hatinfo.o
7+
$(CC) hatinfo.o $(LIBS) -o hatinfo
8+
9+
hatinfo.o: hatinfo.c
10+
$(CC) $(CFLAGS) hatinfo.c
11+
12+
clean:
13+
rm *.o hatinfo

0 commit comments

Comments
 (0)