560 lines
16 KiB
NASM
560 lines
16 KiB
NASM
; ***************************************************************************
|
|
; copyright : (C) 2025 by Martin Preuss
|
|
; email : martin@libchipcard.de
|
|
;
|
|
; ***************************************************************************
|
|
; * This file is part of the project "AqHome". *
|
|
; * Please see toplevel file COPYING of that project for license details. *
|
|
; ***************************************************************************
|
|
|
|
|
|
|
|
; ***************************************************************************
|
|
; defines
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; network interfaces
|
|
|
|
.equ NETDEV0_IFACENUM = 1
|
|
.equ NETDEV1_IFACENUM = 2
|
|
|
|
|
|
|
|
; ***************************************************************************
|
|
; data
|
|
|
|
.dseg
|
|
|
|
appRouterDataBegin:
|
|
appRouterRangeBegin: .byte 1
|
|
appRouterRangeEnd: .byte 1
|
|
appRouterDataEnd:
|
|
|
|
|
|
|
|
|
|
; ***************************************************************************
|
|
; code
|
|
|
|
.cseg
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine AppRouter_Init @global
|
|
|
|
AppRouter_Init:
|
|
ldi xh, HIGH(appRouterDataBegin)
|
|
ldi xl, LOW(appRouterDataBegin)
|
|
clr r16
|
|
ldi r17, (appRouterDataEnd-appRouterDataBegin)
|
|
rcall Utils_FillSram
|
|
|
|
ldi r16, 0xe0 ; default range from 0xe0-0xef (will be changed later)
|
|
sts netInterfaceData+NET_IFACE_OFFS_ADDRESS, r16 ; use first address for router itself
|
|
sts netInterfaceData2+NET_IFACE_OFFS_ADDRESS, r16 ; use same address for both interfaces to save on addresses
|
|
inc r16
|
|
sts appRouterRangeBegin, r16 ; range from router+1
|
|
ldi r16, 0xef
|
|
sts appRouterRangeEnd, r16
|
|
|
|
rcall appRouterReadConfFromEeprom ; try to read config from EEPROM
|
|
|
|
; set interface number for NETDEV0
|
|
ldi r16, NETDEV0_IFACENUM
|
|
sts netInterfaceData+NET_IFACE_OFFS_IFACENUM, r16
|
|
; set interface number for NETDEV1
|
|
ldi r16, NETDEV1_IFACENUM
|
|
sts netInterfaceData2+NET_IFACE_OFFS_IFACENUM, r16
|
|
|
|
ldi r18, NETMSG_CMD_ADDRESS_RANGE
|
|
rcall appRouterSendRangeMsgToDev1
|
|
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine AppRouter_EveryDay @global
|
|
;
|
|
; @clobbers R16, R17, X
|
|
|
|
AppRouter_EveryDay:
|
|
ldi yl, LOW(netInterfaceData)
|
|
ldi yh, HIGH(netInterfaceData)
|
|
bigcall NET_Interface_ResetStats ; (R16, R17, X)
|
|
|
|
ldi yl, LOW(netInterfaceData2)
|
|
ldi yh, HIGH(netInterfaceData2)
|
|
bigcall NET_Interface_ResetStats ; (R16, R17, X)
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine AppRouter_Run @global
|
|
;
|
|
; Read messages from either interface and forward to the other one.
|
|
|
|
AppRouter_Run:
|
|
rjmp appRouterCheckRecvdMsg
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine appRouterHandleMsgAnyDev @global
|
|
;
|
|
; @param X pointer to received message
|
|
; @return CFLAG set if msg handled, cleared otherwise
|
|
; @clobbers any, !X
|
|
|
|
appRouterHandleMsgAnyDev:
|
|
push xl
|
|
push xh
|
|
rcall appRouterHandleMsgAnyDev_savedX
|
|
pop xh
|
|
pop xl
|
|
rjmp appRouterHandleMsgAnyDev_end
|
|
appRouterHandleMsgAnyDev_savedX:
|
|
adiw xh:xl, NETMSG_OFFS_CMD ; maybe move ping/reboot handling to all/main.asm?
|
|
ld r16, X
|
|
sbiw xh:xl, NETMSG_OFFS_CMD
|
|
cpi r16, NETMSG_CMD_REBOOT_REQUEST
|
|
breq appRouterHandleMsgAnyDev_handleRebootMsg
|
|
cpi r16, NETMSG_CMD_PING
|
|
breq appRouterHandleMsgAnyDev_handlePingMsg
|
|
cpi r16, NETMSG_CMD_VALUE_SET
|
|
breq appRouterHandleMsgAnyDev_handleSetValue
|
|
rjmp appRouterHandleMsgAnyDev_clcRet
|
|
appRouterHandleMsgAnyDev_handleRebootMsg:
|
|
rcall appRouterHandleRebootRequest
|
|
ret
|
|
appRouterHandleMsgAnyDev_handlePingMsg:
|
|
rcall appRouterHandlePingRequest
|
|
clc
|
|
ret
|
|
appRouterHandleMsgAnyDev_handleSetValue:
|
|
rcall NETMSG_ValueRead ; (none)
|
|
cpi r17, VALUE_ID_ROUTER_SETRANGE
|
|
breq appRouterHandleMsgAnyDev_handleSetRange
|
|
rjmp appRouterHandleMsgAnyDev_clcRet
|
|
appRouterHandleMsgAnyDev_handleSetRange:
|
|
sts netInterfaceData+NET_IFACE_OFFS_ADDRESS, r18 ; use first address for router itself
|
|
sts netInterfaceData2+NET_IFACE_OFFS_ADDRESS, r18 ; use same address for both interfaces to save on addresses
|
|
inc r18 ; start range after router
|
|
sts appRouterRangeBegin, r18
|
|
sts appRouterRangeEnd, r19
|
|
; send ACK
|
|
ldi r23, NETMSG_CMD_VALUE_SET_ACK
|
|
rcall Main_SendValueResponse ; (clobbers all, including Y)
|
|
; let subnodes re-eunumerate
|
|
ldi r18, NETMSG_CMD_REENUM
|
|
rcall appRouterSendRangeMsgToDev1 ; (R16, R17, R18, R19, R20, R21, X, Y)
|
|
rcall appRouterWriteConfToEeprom ; (r16, r17, X)
|
|
sec
|
|
ret
|
|
appRouterHandleMsgAnyDev_clcRet:
|
|
clc
|
|
appRouterHandleMsgAnyDev_end:
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine appRouterHandleDev1Msg @global
|
|
;
|
|
; Handle messages from controlled subnet.
|
|
;
|
|
; @param X pointer to received message
|
|
; @return CFLAG set if msg handled, cleared otherwise
|
|
; @clobbers any, !X
|
|
|
|
appRouterHandleDev1Msg:
|
|
push xl
|
|
push xh
|
|
rcall appRouterHandleDev1Msg_savedX
|
|
pop xh
|
|
pop xl
|
|
rjmp appRouterHandleDev1Msg_end
|
|
appRouterHandleDev1Msg_savedX:
|
|
adiw xh:xl, NETMSG_OFFS_CMD
|
|
ld r16, X
|
|
sbiw xh:xl, NETMSG_OFFS_CMD
|
|
cpi r16, NETMSG_CMD_NEED_ADDRESS
|
|
breq appRouterHandleDev1Msg_handleNeedAddr
|
|
cpi r16, NETMSG_CMD_CLAIM_ADDRESS
|
|
breq appRouterHandleDev1Msg_handleClaimAddr
|
|
; add more here
|
|
ldi r16, 0
|
|
rjmp appRouterHandleDev1Msg_clcRet
|
|
appRouterHandleDev1Msg_handleNeedAddr:
|
|
ldi r18, NETMSG_CMD_ADDRESS_RANGE
|
|
rcall appRouterSendRangeMsgToDev1 ; (R16, R17, R18, R19, R20, R21, X, Y)
|
|
sec
|
|
rjmp appRouterHandleDev1Msg_end
|
|
appRouterHandleDev1Msg_handleClaimAddr:
|
|
rcall NETMSG_Address_Read ; R18=cmd, R19=addr(R18, R19)
|
|
rcall appRouterIsR19InRange
|
|
brcs appRouterHandleDev1Msg_end
|
|
; is not in subnet range, deny
|
|
rcall appRouterSendDenyAddrR19ToDev1 ; (R16, R17, R18, R19, R20, R21, X, Y)
|
|
sec
|
|
rjmp appRouterHandleDev1Msg_end
|
|
appRouterHandleDev1Msg_clcRet:
|
|
clc
|
|
appRouterHandleDev1Msg_end:
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine appRouterIsR19InRange
|
|
;
|
|
; @param R19 address to check against range
|
|
; @clobbers R16
|
|
|
|
appRouterIsR19InRange:
|
|
lds r16, appRouterRangeBegin
|
|
cp r19, r16
|
|
brcs appRouterIsR19InRangeClcRet
|
|
lds r16, appRouterRangeEnd
|
|
cp r16, r19
|
|
brcs appRouterIsR19InRangeClcRet
|
|
sec
|
|
rjmp appRouterIsR19InRange_end
|
|
appRouterIsR19InRangeClcRet:
|
|
clc
|
|
appRouterIsR19InRange_end:
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine appRouterSendDenyAddrR19ToDev1
|
|
;
|
|
; @param R19 address to send
|
|
; @clobbers R16, R17, R18, R19, R20, R21, X, Y
|
|
|
|
appRouterSendDenyAddrR19ToDev1:
|
|
ldi r18, NETMSG_CMD_DENY_ADDRESS ; deny addr
|
|
rjmp appRouterSendAddrMsgToDev1 ; (R16, R17, R18, R19, R20, R21, X, Y)
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine appRouterSendAddrMsgToDev1
|
|
;
|
|
; @param R18 command
|
|
; @param R19 address to send
|
|
; @clobbers R16 (R17, R18, R19, R20, R21, X, Y)
|
|
|
|
appRouterSendAddrMsgToDev1:
|
|
bigcall NET_Buffer_Alloc ; (R16, R17, X)
|
|
brcc appRouterSendAddrMsgToDev1_end
|
|
push r16
|
|
adiw xh:xl, 1
|
|
bigcall NETMSG_Address_Write ; (R16, R17, R18, R19, R20, R21)
|
|
sbiw xh:xl, 1
|
|
pop r16
|
|
rcall appRouterSendMsgToDev1 ; (R16, R17, R18, R24, R25, X, Y)
|
|
appRouterSendAddrMsgToDev1_end:
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine appRouterSendRangeMsgToDev1
|
|
;
|
|
; @param R18 msg code
|
|
; @return CFLAG set if message enqueued, cleared on error
|
|
; @clobbers (R16, R17, R18, R19, R20, R21, R24, R25, X, Y)
|
|
|
|
appRouterSendRangeMsgToDev1:
|
|
bigcall NET_Buffer_Alloc ; (R16, R17, X)
|
|
brcc appRouterSendRangeMsgToDev1_end
|
|
push r16
|
|
lds r20, appRouterRangeBegin
|
|
lds r21, appRouterRangeEnd
|
|
adiw xh:xl, 1
|
|
bigcall NETMSG_Range_Write ; (R16, R17, R18, R19, R20, R21)
|
|
sbiw xh:xl, 1
|
|
pop r16
|
|
rcall appRouterSendMsgToDev1 ; (R16, R17, R18, R24, R25, X, Y)
|
|
appRouterSendRangeMsgToDev1_end:
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine appRouterSendMsgToDev1
|
|
;
|
|
; @param R16 num of allocated buffer
|
|
; @param X msg to send (points to start of allocated buffer, e.g. buffer header)
|
|
; @return CFLAG set if message enqueued, cleared on error
|
|
; @clobbers Y (R16, R17, R18, R24, R25, X)
|
|
|
|
appRouterSendMsgToDev1:
|
|
ldi yl, LOW(netInterfaceData2)
|
|
ldi yh, HIGH(netInterfaceData2)
|
|
bigcall NET_Interface_AddOutgoingMsgNum ; (R17, R18, X)
|
|
brcs appRouterSendMsgToDev1_end
|
|
bigcall NET_Buffer_ReleaseByNum ; (R16, X)
|
|
ldi r16, NET_IFACE_OFFS_ERR_NOBUF_LOW
|
|
rcall NET_Interface_IncCounter16 ; (R24, R25)
|
|
clc
|
|
appRouterSendMsgToDev1_end:
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine appRouterHandleRebootRequest
|
|
;
|
|
; Doesn't return if reboot msg is valid.
|
|
;
|
|
; @param X pointer to received message
|
|
|
|
appRouterHandleRebootRequest:
|
|
rcall NETMSG_RebootRequestRead
|
|
brcc appRouterHandleRebootRequest_end
|
|
; reboot
|
|
cli
|
|
bigjmp BOOTLOADER_ADDR
|
|
appRouterHandleRebootRequest_end:
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine appRouterHandlePingRequest
|
|
;
|
|
; @param X pointer to received message
|
|
|
|
appRouterHandlePingRequest:
|
|
adiw xh:xl, NETMSG_OFFS_SRCADDR
|
|
ld r17, X
|
|
push r17
|
|
bigcall NET_Buffer_Alloc ; (R16, R17, X)
|
|
pop r17
|
|
brcc appRouterHandlePingRequest_end ; jmp on error
|
|
push r16 ; buffer num
|
|
mov r16, r17 ; DEST addr
|
|
adiw xh:xl, 1
|
|
ldi yl, LOW(netInterfaceData)
|
|
ldi yh, HIGH(netInterfaceData)
|
|
bigcall NETMSG_Pong_Write ; (R16, R17, R18, R19, R20, X)
|
|
sbiw xh:xl, 1
|
|
pop r16 ; buffer num
|
|
bigcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
|
|
appRouterHandlePingRequest_end:
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine appRouterCheckRecvdMsg
|
|
;
|
|
; Read messages from either interface and forward to the other one.
|
|
;
|
|
; @return CFLAG set if something done, cleared otherwise
|
|
|
|
appRouterCheckRecvdMsg:
|
|
rcall NET_PeekNextIncomingMsgNum ; check read queue (bufNum->r16)
|
|
brcc appRouterCheckRecvdMsg_end ; no msg, jmp
|
|
rcall NET_Buffer_Locate ; (R17)
|
|
rcall appRouterHandleRouterMsgWithHdr ; filter out router msgs
|
|
brcs appRouterCheckRecvdMsg_removeMsg ; handled by router code, don't forward
|
|
; let system handle incoming messages
|
|
adiw xh:xl, 1
|
|
rcall appRouterLetSysHandleMsg
|
|
sbiw xh:xl, 1
|
|
|
|
; forward to other interface
|
|
ld r17, X
|
|
andi r17, (1<<NET_IFACE_BUFFER_IFACENUM1_BIT) | (1<<NET_IFACE_BUFFER_IFACENUM0_BIT)
|
|
rcall appRouterReverseInterfaceNum ; (R16, R17)
|
|
rcall appRouterAddMsgToInterface
|
|
brcc appRouterCheckRecvdMsg_end ; could not add, jmp
|
|
rcall NET_GetNextIncomingMsgNum ; take off the queue
|
|
sec
|
|
ret
|
|
appRouterCheckRecvdMsg_removeMsg:
|
|
rcall NET_GetNextIncomingMsgNum ; take off the queue
|
|
rcall NET_Buffer_ReleaseByNum ; (R16, X)
|
|
sec
|
|
appRouterCheckRecvdMsg_end:
|
|
ret
|
|
; @end
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine appRouterHandleRouterMsgWithHdr
|
|
;
|
|
; @param X pointer to msg
|
|
; @return CFLAG set if msg handled, cleared otherwise
|
|
|
|
appRouterHandleRouterMsgWithHdr:
|
|
ld r17, X
|
|
adiw xh:xl, 1
|
|
andi r17, (1<<NET_IFACE_BUFFER_IFACENUM1_BIT) | (1<<NET_IFACE_BUFFER_IFACENUM0_BIT)
|
|
cpi r17, NETDEV1_IFACENUM
|
|
brne appRouterHandleRouterMsgWithHdr_any
|
|
rcall appRouterHandleDev1Msg ; handle messages from controlled subnet
|
|
brcs appRouterHandleRouterMsgWithHdr_msgHandled
|
|
appRouterHandleRouterMsgWithHdr_any:
|
|
rcall appRouterHandleMsgAnyDev ; handle any msg
|
|
brcs appRouterHandleRouterMsgWithHdr_msgHandled
|
|
sbiw xh:xl, 1 ; CFLAG cleared
|
|
rjmp appRouterHandleRouterMsgWithHdr_end
|
|
appRouterHandleRouterMsgWithHdr_msgHandled:
|
|
sbiw xh:xl, 1
|
|
sec
|
|
appRouterHandleRouterMsgWithHdr_end:
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine appRouterLetSysHandleMsg
|
|
;
|
|
; @param X pointer to msg to handle (point behind the buffer header!)
|
|
; @clobbers any, !X
|
|
|
|
appRouterLetSysHandleMsg:
|
|
ld r16, X
|
|
cpi r16, 0xff
|
|
breq appRouterLetSysHandleMsg_forMe
|
|
lds r17, netInterfaceData+NET_IFACE_OFFS_ADDRESS
|
|
cp r16, r17
|
|
brne appRouterLetSysHandleMsg_end
|
|
appRouterLetSysHandleMsg_forMe:
|
|
push xl
|
|
push xh
|
|
rcall onMessageReceived
|
|
pop xh
|
|
pop xl
|
|
push xl
|
|
push xh
|
|
rcall mainModulesOnPacketReceived
|
|
pop xh
|
|
pop xl
|
|
push xl
|
|
push xh
|
|
rcall mainAppsOnPacketReceived
|
|
pop xh
|
|
pop xl
|
|
appRouterLetSysHandleMsg_end:
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine appRouterReverseInterfaceNum
|
|
;
|
|
; @param r17 buffer num
|
|
; @return r17 reversed interface number
|
|
; @clobbers r16, r17
|
|
|
|
appRouterReverseInterfaceNum:
|
|
ldi r16, (1<<NET_IFACE_BUFFER_IFACENUM1_BIT) | (1<<NET_IFACE_BUFFER_IFACENUM0_BIT)
|
|
eor r17, r16
|
|
and r17, r16
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine appRouterAddMsgToInterface
|
|
; @param r16 buffer num
|
|
; @param r17 interface num
|
|
|
|
appRouterAddMsgToInterface:
|
|
cpi r17, NETDEV0_IFACENUM
|
|
brne appRouterAddMsgToInterface_notNetDev0
|
|
ldi yl, LOW(netInterfaceData)
|
|
ldi yh, HIGH(netInterfaceData)
|
|
rjmp NET_Interface_AddOutgoingMsgNum ; try to add msg to interface
|
|
appRouterAddMsgToInterface_notNetDev0:
|
|
ldi yl, LOW(netInterfaceData2)
|
|
ldi yh, HIGH(netInterfaceData2)
|
|
rjmp NET_Interface_AddOutgoingMsgNum ; try to add msg to interface
|
|
appRouterAddMsgToInterface_end:
|
|
clc
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine appRouterWriteConfToEeprom
|
|
;
|
|
; @clobbers R16, X (R17)
|
|
|
|
appRouterWriteConfToEeprom:
|
|
; write range begin
|
|
ldi xl, LOW(EEPROM_OFFS_ROUTER_RANGE_BEGIN)
|
|
ldi xh, HIGH(EEPROM_OFFS_ROUTER_RANGE_BEGIN)
|
|
lds r16, appRouterRangeBegin
|
|
rcall Eeprom_WriteByteIfChanged ; (R17)
|
|
brcc appRouterWriteConfToEeprom_end
|
|
|
|
; write range end
|
|
ldi xl, LOW(EEPROM_OFFS_ROUTER_RANGE_END)
|
|
ldi xh, HIGH(EEPROM_OFFS_ROUTER_RANGE_END)
|
|
lds r16, appRouterRangeEnd
|
|
rcall Eeprom_WriteByteIfChanged ; (R17)
|
|
appRouterWriteConfToEeprom_end:
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine appRouterReadConfFromEeprom
|
|
;
|
|
; @clobbers R16, X (R17)
|
|
|
|
appRouterReadConfFromEeprom:
|
|
; read range begin
|
|
ldi xl, LOW(EEPROM_OFFS_ROUTER_RANGE_BEGIN)
|
|
ldi xh, HIGH(EEPROM_OFFS_ROUTER_RANGE_BEGIN)
|
|
rcall Eeprom_ReadByte
|
|
brcc appRouterReadConfFromEeprom_end
|
|
cpi r16, 0xff
|
|
breq appRouterReadConfFromEeprom_okay ; not set, jmp
|
|
cpi r16, 2 ; range should at least start at 2 to assign 1 to router
|
|
brcs appRouterReadConfFromEeprom_okay
|
|
sts appRouterRangeBegin, r16
|
|
dec r16
|
|
sts netInterfaceData+NET_IFACE_OFFS_ADDRESS, r16 ; use addr rangeBegin-1 for router itself
|
|
sts netInterfaceData2+NET_IFACE_OFFS_ADDRESS, r16 ; use same address for both interfaces to save on addresses
|
|
|
|
; read range end
|
|
ldi xl, LOW(EEPROM_OFFS_ROUTER_RANGE_END)
|
|
ldi xh, HIGH(EEPROM_OFFS_ROUTER_RANGE_END)
|
|
rcall Eeprom_ReadByte
|
|
brcc appRouterReadConfFromEeprom_end
|
|
cpi r16, 0xff
|
|
breq appRouterReadConfFromEeprom_okay
|
|
sts appRouterRangeEnd, r16
|
|
appRouterReadConfFromEeprom_okay:
|
|
sec
|
|
appRouterReadConfFromEeprom_end:
|
|
ret
|
|
; @end
|
|
|
|
|
|
|