使用 Microchip SAM9X60 OTP 存储板卡的MAC地址和序列号

echo "Programming OTP:"
echo " $0 22041100001 00:60:2D:0C:84:27"

}

function prog_mac(){
# get serial number
SN=$1
if [ KaTeX parse error: Expected '}', got '#' at position 2: {#̲SN} -ne 11 ]; t…{SN:3:11}
SN_2=0x00000${SN:0:3}
echo “SN_1: $SN_1”
echo “SN_2: $SN_2”
fi

# get mac address
MAC\_ADDR=$2
if [ ${#MAC\_ADDR} -ne 17 ]; then
    echo "ERROR: The format of MAC adddress you program is error."
    usage
    exit 1
else
    /sbin/ifconfig eth0 down
    /sbin/ifconfig eth0 hw ether "$MAC\_ADDR"
    if [ $? -eq 0 ]; then
        echo "MAC address is valid, can be programmed OTP."
        /sbin/ifconfig eth0 up
    else
        echo "MAC address is not valid."
        /sbin/ifconfig eth0 up
        usage
        exit 1
    fi
    echo "Start programming OTP ......"
    MAC\_ADDR\_1=`echo $MAC\_ADDR | awk '{split($0,addr,":");print addr[1]}'`
    MAC\_ADDR\_2=`echo $MAC\_ADDR | awk '{split($0,addr,":");print addr[2]}'`
    MAC\_ADDR\_3=`echo $MAC\_ADDR | awk '{split($0,addr,":");print addr[3]}'`
    MAC\_ADDR\_4=`echo $MAC\_ADDR | awk '{split($0,addr,":");print addr[4]}'`
    MAC\_ADDR\_5=`echo $MAC\_ADDR | awk '{split($0,addr,":");print addr[5]}'`
    MAC\_ADDR\_6=`echo $MAC\_ADDR | awk '{split($0,addr,":");print addr[6]}'`

    HW\_OCOTP\_MAC0=0x${MAC\_ADDR\_3}${MAC\_ADDR\_4}${MAC\_ADDR\_5}${MAC\_ADDR\_6}
    HW\_OCOTP\_MAC1=0x0000${MAC\_ADDR\_1}${MAC\_ADDR\_2}
    echo "HW\_OCOTP\_MAC0: $HW\_OCOTP\_MAC0"
    echo "HW\_OCOTP\_MAC1: $HW\_OCOTP\_MAC1"
fi 

##
## Steps for program OTPC
##

###
### Write Access
###
# read RC register
echo "Read PMC Clock Generator Main Oscillator Register"
devmem 0xfffffc20
# enable RC clock
echo "Enable the main RC in CKGR\_MOR register"
devmem 0xfffffc20 32 0x01370829
# read RC register again
echo "Read PMC Clock Generator Main Oscillator Register again"
devmem 0xfffffc20

# write OTPC\_MR.NPCKT to 0
echo "write OTPC\_MR.NPCKT to 0"
devmem 0xeff00004 32 0x00000000
# write OTPC\_MR.ADDR to its maximum value
echo "write OTPC\_MR.ADDR to its maximum value"
devmem 0xeff00004 32 0x00ff0000
# write OTPC\_CR.READ to 1 and wait for the read completion
echo "write OTPC\_CR.READ to 1 and wait for the read completion"
devmem 0xeff00000 32 0x71670040
sleep 1

echo "check if End of Read (EOR bit8) is 1"
devmem 0xeff0001c
echo "check OTPC Header Register"
devmem 0xeff00020
echo "check OTPC Data Register if have data of one"
devmem 0xeff00024

# Write OTPC\_MR.ADDR to 0 and set NPCKT
devmem 0xeff00004 32 0x00000010
# write the header value in OTPC\_HR
devmem 0xeff00020 32 0x00000301
# set DADDR to 0
devmem 0xeff00008 32 0x00010000
# write serial number into payload0 and payload1
devmem 0xeff00024 32 $SN\_1
devmem 0xeff00024 32 $SN\_2
# write eth0 mac address into payload2 and payload3
devmem 0xeff00024 32 $HW\_OCOTP\_MAC0
devmem 0xeff00024 32 $HW\_OCOTP\_MAC1

# after write , enable OTPC programming
devmem 0xeff00000 32 0x71670001
sleep 1
# check if programming is end
devmem 0xeff0001c
sleep 1
# read the address of new generated packet
val=`devmem 0xeff00004`
echo "the address of new generated packet: $val"
val=0x${val:2:4}0000
# clear OTPC\_MR.NPCKT
devmem 0xeff00004 32 $val

###
### Read data from OTP to check if write ok
###
devmem 0xeff00000 32 0x00000040
devmem 0xeff0001c
devmem 0xeff00020
devmem 0xeff00008 32 0x00000000
SN\_1\_OTP=`devmem 0xeff00024`
echo "SN\_1\_OTP = $SN\_1\_OTP"

SN\_2\_OTP=`devmem 0xeff00024`
echo "SN\_2\_OTP = $SN\_2\_OTP"

HW\_OCOTP\_MAC0\_OTP=`devmem 0xeff00024`
echo "HW\_OCOTP\_MAC0\_OTP = $HW\_OCOTP\_MAC0\_OTP"
HW\_OCOTP\_MAC0\_OTP=${HW\_OCOTP\_MAC0\_OTP:2:9}
# transfer HEX to DEC
HW\_OCOTP\_MAC0\_OTP=$((16#$HW\_OCOTP\_MAC0\_OTP))

HW\_OCOTP\_MAC1\_OTP=`devmem 0xeff00024`
echo "HW\_OCOTP\_MAC1\_OTP = $HW\_OCOTP\_MAC1\_OTP"
HW\_OCOTP\_MAC1\_OTP=${HW\_OCOTP\_MAC1\_OTP:2:9}
# transfer HEX to DEC
HW\_OCOTP\_MAC1\_OTP=$((16#$HW\_OCOTP\_MAC1\_OTP))

## transfer writen value from HEX to DEC
HW\_OCOTP\_MAC0=${HW\_OCOTP\_MAC0:2:9}
# transfer HEX to DEC
HW\_OCOTP\_MAC0=$((16#$HW\_OCOTP\_MAC0))
HW\_OCOTP\_MAC1=${HW\_OCOTP\_MAC1:2:9}
# transfer HEX to DEC
HW\_OCOTP\_MAC1=$((16#$HW\_OCOTP\_MAC1))

if [ "$SN\_1\_OTP" == "$SN\_1" ] && [ "$SN\_2\_OTP" == "$SN\_2" ] && [ $HW\_OCOTP\_MAC0\_OTP -eq $HW\_OCOTP\_MAC0 ] && [ $HW\_OCOTP\_MAC1\_OTP -eq $HW\_OCOTP\_MAC1 ]; then
    echo "Programming MAC ADDR and serial number succussful."
else
    echo "Programming OTP FAIL."
fi

###
### Lock the new generated packet
###
echo "Lock the new generated packet"
# write the address value of the header of the packet to lock in OTPC\_MR.ADDR
devmem 0xeff00004 32 $val
# start a read by seeting OTPC\_CR.READ and waiting for the read completion indicated by OTPC\_ISR.EOR
devmem 0xeff00000 32 0x00000040
sleep 1
# check if End of Read (EOR bit8) is 1
devmem 0xeff0001c
# Write 0x7167 in the OTPC\_CR.KEY field and '1' in OTPC\_CR.CKSGEN
devmem 0xeff00000 32 0x71670002
# the end of the lock operation is indicated by OTPC\_ISR.EOL='1' and/or OTPC\_SR.LOCK='0'
lock\_ret=`devmem 0xeff0001c`
eol=${lock\_ret:9}
if [ $eol -eq 2 ]; then
    echo "Lock ok."
else
    echo "Lock fail."
fi

}

Entry

if [ $# == 2 ];then
prog_mac $@
else
usage
exit 1
fi

exit 0


#### 4.2. Read


    又写了一个读取MAC地址和SN的shell脚本 get\_Mac.sh,可以用于板子 Linux系统启动后,运行该脚本从OTP相应的Aera中读取MAC address,如果读取失败会随机生成一个MAC地址,然后通过ifconfig eth0 hw ether 命令配置网卡的IP。脚本还会从OTP读取序列号,并写入到文件 /images/data/SN 中。


get\_Mac.sh 脚本源码如下。



#!/bin/sh

add by heat

Steps for set MAC address and get SN from OTPC

read RC register

echo “read RC register”
/sbin/devmem 0xfffffc20

enable RC clock

echo “enable the main RC in CKGR_MOR register”
/sbin/devmem 0xfffffc20 32 0x01370829

read RC register again

echo “read RC register again”
/sbin/devmem 0xfffffc20

write the address of header into OTPC_MR

/sbin/devmem 0xeff00004 32 0x00000000

OTPC_CR.READ set to 1 to enable user area

/sbin/devmem 0xeff00000 32 0x00000040

check OTPC_ISR.EOR if 0 to wait for start reading

/sbin/devmem 0xeff0001c
sleep 1

read the header of the packet

/sbin/devmem 0xeff00020

start address of payload

/sbin/devmem 0xeff00008 32 0x00000000

start reading value from OTP

SN_TAIL=/sbin/devmem 0xeff00024
SN_HEAD=/sbin/devmem 0xeff00024
MAC0_TAIL=/sbin/devmem 0xeff00024
MAC0_HEAD=/sbin/devmem 0xeff00024
echo “SN_TAIL= S N _ T A I L " e c h o " S N _ H E A D = SN\_TAIL" echo "SN\_HEAD= SN_TAIL"echo"SN_HEAD=SN_HEAD”
echo “MAC0_TAIL= M A C 0 _ T A I L " e c h o " M A C 0 _ H E A D = MAC0\_TAIL" echo "MAC0\_HEAD= MAC0_TAIL"echo"MAC0_HEAD=MAC0_HEAD”

if [ $MAC0_TAIL == “0x00000000” ] && [ $MAC0_HEAD == “0x00000000” ]; then
echo “Cannot get correct data from OTP address 0x0, try to read from OTP address 0x29”
# write the address of header into OTPC_MR
/sbin/devmem 0xeff00004 32 0x00290000
# OTPC_CR.READ set to 1 to enable user area
/sbin/devmem 0xeff00000 32 0x00000040
# check OTPC_ISR.EOR if 0 to wait for start reading
/sbin/devmem 0xeff0001c
sleep 1
# read the header of the packet
/sbin/devmem 0xeff00020
# start address of payload
/sbin/devmem 0xeff00008 32 0x00000000

# start reading value from OTP
SN\_TAIL=`/sbin/devmem 0xeff00024`
SN\_HEAD=`/sbin/devmem 0xeff00024`
MAC0\_TAIL=`/sbin/devmem 0xeff00024`
MAC0\_HEAD=`/sbin/devmem 0xeff00024`
echo "SN\_TAIL=$SN\_TAIL"
echo "SN\_HEAD=$SN\_HEAD"
echo "MAC0\_TAIL=$MAC0\_TAIL"
echo "MAC0\_HEAD=$MAC0\_HEAD"

fi

NONE_MAC0=false
NONE_MAC1=false

analyse eth0 MAC address

if [ $MAC0_TAIL == “0x00000000” ] && [ $MAC0_HEAD == “0x00000000” ]; then
echo “Cannot get correct MAC address form OTP”
echo “Use Random MAC Address”
MAC0_ADDR_RAND=echo $RANDOM|md5sum
MAC0_ADDR_1=00
MAC0_ADDR_2=1F
MAC0_ADDR_3=55
MAC0_ADDR_4=echo $MAC0\_ADDR\_RAND|cut -c 1-2
MAC0_ADDR_5=echo $MAC0\_ADDR\_RAND|cut -c 3-4
MAC0_ADDR_6=echo $MAC0\_ADDR\_RAND|cut -c 5-6
else
case ${#MAC0_TAIL} in
2)
MAC0_OPT_SECTOR_TAIL=“0x00000000”
;;
3)
MAC0_OPT_SECTOR_TAIL="0x0000000"echo $MAC0\_TAIL | cut -b 3
;;
4)
MAC0_OPT_SECTOR_TAIL="0x000000"echo $MAC0\_TAIL | cut -b 3-4
;;
5)
MAC0_OPT_SECTOR_TAIL="0x00000"echo $MAC0\_TAIL | cut -b 3-5
;;
6)
MAC0_OPT_SECTOR_TAIL="0x0000"echo $MAC0\_TAIL | cut -b 3-6
;;
7)
MAC0_OPT_SECTOR_TAIL="0x000"echo $MAC0\_TAIL | cut -b 3-7
;;
8)
MAC0_OPT_SECTOR_TAIL="0x00"echo $MAC0\_TAIL | cut -b 3-8
;;
9)
MAC0_OPT_SECTOR_TAIL="0x0"echo $MAC0\_TAIL | cut -b 3-9
;;
10)
MAC0_OPT_SECTOR_TAIL=$MAC0_TAIL
;;
*)
NONE_MAC0=true
;;
esac
case ${#MAC0_HEAD} in
2)
MAC0_OPT_SECTOR_HEAD=“0x0000”
;;
3)
MAC0_OPT_SECTOR_HEAD="0x000"echo $MAC0\_HEAD | cut -b 3
;;
4)
MAC0_OPT_SECTOR_HEAD="0x00"echo $MAC0\_HEAD | cut -b 3-4
;;
5)
MAC0_OPT_SECTOR_HEAD="0x0"echo $MAC0\_HEAD | cut -b 3-5
;;
6)
MAC0_OPT_SECTOR_HEAD="0x0000"echo $MAC0\_HEAD | cut -b 3-6
;;
7)
MAC0_OPT_SECTOR_HEAD="0x000"echo $MAC0\_HEAD | cut -b 3-7
;;
8)
MAC0_OPT_SECTOR_HEAD="0x00"echo $MAC0\_HEAD | cut -b 3-8
;;
9)
MAC0_OPT_SECTOR_HEAD="0x0"echo $MAC0\_HEAD | cut -b 3-9
;;
10)
MAC0_OPT_SECTOR_HEAD=$MAC0_HEAD
;;

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年嵌入式&物联网开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新!!

…(img-9qoe7gNm-1715677234172)]

[外链图片转存中…(img-VUqOWcUK-1715677234172)]

[外链图片转存中…(img-aIxLneEi-1715677234173)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值