mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-22 13:29:01 +00:00
add interrupts
This commit is contained in:
@@ -84,6 +84,7 @@ type CAN struct {
|
|||||||
Interrupt interrupt.Interrupt
|
Interrupt interrupt.Interrupt
|
||||||
instance uint8
|
instance uint8
|
||||||
alwaysFD bool
|
alwaysFD bool
|
||||||
|
rxInterrupt bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// CANTransferRate represents CAN bus transfer rates
|
// CANTransferRate represents CAN bus transfer rates
|
||||||
@@ -115,8 +116,9 @@ type CANConfig struct {
|
|||||||
Mode CANMode
|
Mode CANMode
|
||||||
Tx Pin
|
Tx Pin
|
||||||
Rx Pin
|
Rx Pin
|
||||||
Standby Pin // Optional standby pin for CAN transceiver (set to NoPin if not used)
|
Standby Pin // Optional standby pin for CAN transceiver (set to NoPin if not used)
|
||||||
AlwaysFD bool // Always transmit as FD frames, even when data fits in classic CAN
|
AlwaysFD bool // Always transmit as FD frames, even when data fits in classic CAN
|
||||||
|
EnableRxInterrupt bool // Enable interrupt-driven receive (messages delivered via SetRxCallback)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CANFilterConfig represents a message filter configuration
|
// CANFilterConfig represents a message filter configuration
|
||||||
@@ -145,6 +147,10 @@ func enableFDCANClock() {
|
|||||||
// flags implemented as described in [CAN.SetRxCallback]
|
// flags implemented as described in [CAN.SetRxCallback]
|
||||||
var canRxCB [2]func(data []byte, id uint32, extendedID bool, timestamp uint32, flags uint32)
|
var canRxCB [2]func(data []byte, id uint32, extendedID bool, timestamp uint32, flags uint32)
|
||||||
|
|
||||||
|
// canInstances tracks CAN peripherals with interrupt-driven RX enabled.
|
||||||
|
// A non-nil entry means setRxCallback was called with a non-nil callback.
|
||||||
|
var canInstances [2]*CAN
|
||||||
|
|
||||||
// Configure initializes the FDCAN peripheral and starts it.
|
// Configure initializes the FDCAN peripheral and starts it.
|
||||||
func (can *CAN) Configure(config CANConfig) error {
|
func (can *CAN) Configure(config CANConfig) error {
|
||||||
can.alwaysFD = config.AlwaysFD
|
can.alwaysFD = config.AlwaysFD
|
||||||
@@ -332,23 +338,50 @@ func (can *CAN) tx(id uint32, extendedID bool, data []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// rxFIFOLevel implements [CAN.RxFIFOLevel].
|
// rxFIFOLevel implements [CAN.RxFIFOLevel].
|
||||||
|
// Returns 0,0 when interrupt-driven (messages delivered via callback).
|
||||||
func (can *CAN) rxFIFOLevel() (int, int) {
|
func (can *CAN) rxFIFOLevel() (int, int) {
|
||||||
|
if canInstances[can.instance] != nil {
|
||||||
|
return 0, 0
|
||||||
|
}
|
||||||
level := int(can.Bus.RXF0S.Get() & 0x0F) // F0FL[3:0]
|
level := int(can.Bus.RXF0S.Get() & 0x0F) // F0FL[3:0]
|
||||||
return level, sramcanRF0Nbr
|
return level, sramcanRF0Nbr
|
||||||
}
|
}
|
||||||
|
|
||||||
// setRxCallback implements [CAN.SetRxCallback].
|
// setRxCallback implements [CAN.SetRxCallback].
|
||||||
|
// When cb is non-nil, interrupt-driven receive is enabled on RX FIFO 0.
|
||||||
|
// The CAN.Interrupt field must be initialized with interrupt.New in the board file.
|
||||||
func (can *CAN) setRxCallback(cb func(data []byte, id uint32, extendedID bool, timestamp uint32, flags uint32)) {
|
func (can *CAN) setRxCallback(cb func(data []byte, id uint32, extendedID bool, timestamp uint32, flags uint32)) {
|
||||||
canRxCB[can.instance] = cb
|
canRxCB[can.instance] = cb
|
||||||
|
if cb != nil {
|
||||||
|
canInstances[can.instance] = can
|
||||||
|
// Enable RX FIFO 0 new message interrupt, routed to interrupt line 0.
|
||||||
|
can.Bus.SetIE_RF0NE(1)
|
||||||
|
can.Bus.SetILS_RxFIFO0(0)
|
||||||
|
can.Bus.SetILE_EINT0(1)
|
||||||
|
can.Interrupt.Enable()
|
||||||
|
} else {
|
||||||
|
can.Bus.SetIE_RF0NE(0)
|
||||||
|
canInstances[can.instance] = nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// rxPoll implements [CAN.RxPoll].
|
// rxPoll implements [CAN.RxPoll].
|
||||||
|
// No-op when interrupt-driven receive is active.
|
||||||
func (can *CAN) rxPoll() error {
|
func (can *CAN) rxPoll() error {
|
||||||
|
if canInstances[can.instance] != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
cb := canRxCB[can.instance]
|
cb := canRxCB[can.instance]
|
||||||
if cb == nil {
|
if cb == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
processRxFIFO0(can, cb)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// processRxFIFO0 drains RX FIFO 0 and delivers each message to cb.
|
||||||
|
// Used by both rxPoll (poll mode) and canHandleInterrupt (interrupt mode).
|
||||||
|
func processRxFIFO0(can *CAN, cb func(data []byte, id uint32, extendedID bool, timestamp uint32, flags uint32)) {
|
||||||
for can.Bus.RXF0S.Get()&0x0F != 0 {
|
for can.Bus.RXF0S.Get()&0x0F != 0 {
|
||||||
getIndex := (can.Bus.RXF0S.Get() >> 8) & 0x03 // F0GI[1:0]
|
getIndex := (can.Bus.RXF0S.Get() >> 8) & 0x03 // F0GI[1:0]
|
||||||
rxAddr := can.sramBase() + sramcanRF0SA + uintptr(getIndex)*sramcanRF0Size
|
rxAddr := can.sramBase() + sramcanRF0SA + uintptr(getIndex)*sramcanRF0Size
|
||||||
@@ -399,7 +432,24 @@ func (can *CAN) rxPoll() error {
|
|||||||
can.Bus.RXF0A.Set(uint32(getIndex))
|
can.Bus.RXF0A.Set(uint32(getIndex))
|
||||||
cb(buf[:dataLen], id, extendedID, timestamp, flags)
|
cb(buf[:dataLen], id, extendedID, timestamp, flags)
|
||||||
}
|
}
|
||||||
return nil
|
}
|
||||||
|
|
||||||
|
// canHandleInterrupt is the shared interrupt handler for FDCAN interrupt line 0 (IRQ_TIM16).
|
||||||
|
// Both FDCAN1 and FDCAN2 share this IRQ vector.
|
||||||
|
func canHandleInterrupt(interrupt.Interrupt) {
|
||||||
|
for i := range canInstances {
|
||||||
|
can := canInstances[i]
|
||||||
|
if can == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ir := can.Bus.IR.Get()
|
||||||
|
if ir&FDCAN_IT_RX_FIFO0_NEW_MESSAGE != 0 {
|
||||||
|
can.Bus.IR.Set(FDCAN_IT_RX_FIFO0_NEW_MESSAGE) // Write 1 to clear
|
||||||
|
if cb := canRxCB[i]; cb != nil {
|
||||||
|
processRxFIFO0(can, cb)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConfigureFilter configures a message acceptance filter.
|
// ConfigureFilter configures a message acceptance filter.
|
||||||
|
|||||||
Reference in New Issue
Block a user