Failed to fetch fork details. Try again later.
-
A Sundbom authored5ccf910d
Forked from
Embedded Rust / lpc43xx-hal
Source project has a limited visibility.
#![feature(panic_info_message)]
#![no_main]
#![no_std]
extern crate panic_halt;
use lpc43xx_hal::{
can::{
CanBus,
MsgIface,
MsgObj,
IntoCanTx,
IntoCanRx,
CanRx,
CanTx,
},
io::pin::{
split_ports, PinSplit, Pin,
E, U0, U1, U2, U3,
},
pac,
serial::Serial,
timer::{Timer, EMC0_A, InterruptType, MR0I_A, MR0R_A, MR0S_A, NoMatchPin, NoCapturePin},
};
use pac::{
c_can1::cntl::{DAR_A, EIE_A, IE_A, SIE_A},
usart0::lcr::{BC_A, DLAB_A, PE_A, PS_A, SBS_A, WLS_A},
SCU,
};
use heapless::consts::U32;
static TIMER_PERIOD: u32 = 8192;
// Panic handler for USART3
// use lpc43xx_hal::{debug::PanicInfo, uart_panic_handler};
// uart_panic_handler!(pac::USART3);
use core::fmt::Write;
use rtfm::app;
type Timer0 = Timer<pac::TIMER0, NoMatchPin, NoMatchPin, NoMatchPin, NoMatchPin, NoCapturePin, NoCapturePin, NoCapturePin, NoCapturePin>;
type Can0Rd = Pin<E, U2, CanRx<pac::C_CAN0>>;
type Can0Td = Pin<E, U3, CanTx<pac::C_CAN0>>;
type Can1Rd = Pin<E, U1, CanRx<pac::C_CAN1>>;
type Can1Td = Pin<E, U0, CanTx<pac::C_CAN1>>;
#[app(device = lpc43xx_pac)]
const APP: () = {
static mut TIMER: Timer0 = ();
static mut UART: Serial<pac::USART3> = ();
static mut CAN_0: CanBus<pac::C_CAN0, U32> = ();
static mut CAN_1: CanBus<pac::C_CAN1, U32> = ();
static mut TX_OBJ: MsgObj = ();
static mut TX_STATE: u8 = ();
#[init]
fn init() -> init::LateResources {
let tx_state: u8 = 0;
// Pins
let ports = split_ports(device.SCU, device.GPIO_PORT);
let port_9 = ports
.port_9
.split_pins();
let port_e = ports
.port_e
.split_pins();
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
let can_0_td: Can0Td = port_e.pe_3.into_can_tx();
let can_0_rd: Can0Rd = port_e.pe_2.into_can_rx();
let can_1_td: Can1Td = port_e.pe_0.into_can_tx();
let can_1_rd: Can1Rd = port_e.pe_1.into_can_rx();
let uart_tx = port_9.p9_3;
let uart_rx = port_9.p9_4;
// ========= TIMER INITIALIZATION ==========
let mut timer = Timer0::new_no_pins(device.TIMER0);
timer.start_timer(false);
timer.set_match(0, TIMER_PERIOD);
timer.set_prescaler(1024, Some(0));
unsafe {
timer.mr0(MR0I_A::INTERRUPT, MR0R_A::RESET, MR0S_A::NO_STOP, EMC0_A::NOP);
}
timer.start_timer(true);
// ========= SERIAL OUTPUT INITIALIZATION ==========
let mut serial =
Serial::<pac::USART3>::new(device.USART3, uart_tx, uart_rx, 0x41, 0x0, 0x0);
serial.lcr(
WLS_A::_8_BIT_CHARACTER_LENGTH,
SBS_A::_1_STOP_BIT,
PE_A::DISABLE_PARITY_GENERERATION,
PS_A::ODD_PARITY,
BC_A::DISABLED,
DLAB_A::DISABLED,
);
serial.ier(true, false, false, false, false);
// Configure PLL1 for use with UART3
unsafe {
// Select the IRC as BASE_M4_CLK source
device.CGU.base_m4_clk.write(|w| w.clk_sel().bits(0x1));
// Enable the crystal oscillator
device.CGU.xtal_osc_ctrl.modify(|_, w| w.hf().bit(false));
device
.CGU
.xtal_osc_ctrl
.modify(|_, w| w.enable().bit(false));
// Wait 250us
for i in 0..9_000 {
core::ptr::read_volatile(&i);
}
device.CGU.pll1_ctrl.write(|w| {
w.pd()
.bit(false)
.clk_sel()
.bits(0x6) // Select the crystal oscillator as clock source
.msel()
.bits(20)
.nsel()
.bits(1) // Select the M and N divider values
.psel()
.bits(0)
.fbsel()
.bit(true)
.bypass()
.bit(false)
.direct()
.bit(false)
});
// Wait for the PLL to lock
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
while !device.CGU.pll1_stat.read().lock().bit() {}
// Set PLL1 p-divider to divide by 2 (DIRECT=0; PSEL=0)
device
.CGU
.pll1_ctrl
.modify(|_, w| w.direct().bit(false).psel().bits(0x0));
// Select PLL1 as base_m4_clk source
device.CGU.base_m4_clk.modify(|_, w| w.clk_sel().bits(0x09));
// Wait for 50us
for i in 0..1800 {
core::ptr::read_volatile(&i);
}
// Enable direct output mode
device.CGU.pll1_ctrl.modify(|_, w| w.direct().bit(true));
// Enable clock on UART3
device.CGU.base_uart3_clk.write(|w| w.clk_sel().bits(0x09));
}
// ========= CAN 0 INITIALIZATION ==========
let mut can_0 = CanBus::<pac::C_CAN0, U32>::new(device.C_CAN0, can_0_td, can_0_rd);
can_0.initialize(
12_000_000,
500000,
IE_A::ENABLE_CAN_INTERRUPTS,
SIE_A::ENABLE_STATUS_CHANGE_INTERRUPTS,
EIE_A::DISABLE_ERROR_INTERRUPTS,
DAR_A::ENABLED,
false,
);
// Object setup
let tx_obj = MsgObj::new_tx_obj(true, 0x200, 0x8, 0xDEADBEEF, 0x8008135);
// ========= CAN 1 INITIALIZATION ==========
let mut can_1 = CanBus::<pac::C_CAN1, U32>::new(device.C_CAN1, can_1_td, can_1_rd);
can_1.initialize(
12_000_000,
500000,
IE_A::ENABLE_CAN_INTERRUPTS,
SIE_A::ENABLE_STATUS_CHANGE_INTERRUPTS,
EIE_A::DISABLE_ERROR_INTERRUPTS,
DAR_A::ENABLED,
false,
);
let rx_obj = MsgObj::new_rx_obj(true, 0x200, 0x8, 0xfffffff);
can_1.transfer_obj(MsgIface::Iface1, 1, &rx_obj);
init::LateResources {
TX_OBJ: tx_obj,
TIMER: timer,
UART: serial,
CAN_0: can_0,
CAN_1: can_1,
TX_STATE: tx_state,
}
}
#[interrupt(resources = [UART, TIMER, CAN_0, TX_OBJ, TX_STATE])]
fn TIMER0() {
match resources.TX_STATE {
0 => resources
.TX_OBJ
.msgval(false)
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
.mctrl_txrqst(false)
.cmdmsk_txrqst(false)
.data_a(true)
.data_b(true),
1 => resources
.TX_OBJ
.msgval(false)
.newdat(true)
.mctrl_txrqst(true)
.cmdmsk_txrqst(true),
2 => resources
.TX_OBJ
.msgval(true)
.mctrl_txrqst(true)
.cmdmsk_txrqst(true),
_ => resources
.TX_OBJ
.msgval(false)
.mctrl_txrqst(false)
.cmdmsk_txrqst(false),
};
// write!(resources.UART, "[TIMER_0] {:?}", resources.TX_OBJ);
*resources.TX_STATE += if *resources.TX_STATE < 4 { 1 } else { 0 };
resources
.CAN_0
.transfer_obj(MsgIface::Iface1, 1, &resources.TX_OBJ);
resources
.TIMER
.clear_interrupt(InterruptType::MatchChannel, 0);
}
#[interrupt(resources = [TX_OBJ, CAN_0, UART])]
fn C_CAN0() {
let stat = resources.CAN_0.can.stat.read();
if stat.txok().bit() {
resources
.CAN_0
.can
.stat
.write(|w| w.txok().bit(false).rxok().bit(false));
write!(
resources.UART,
"[CAN 0] message transmitted, status 0x{:x}\r\n",
stat.bits()
)
.unwrap();
}
}
#[interrupt(resources = [CAN_1, UART])]
fn C_CAN1() {
match resources.CAN_1.receive_obj(MsgIface::Iface1) {
Ok(r) => write!(resources.UART, "[CAN_1] message received: {:?}\r\n", r),
Err(u) => match u {
Ok(status) => write!(resources.UART, "[CAN_1] status updated: 0x{:x}\r\n", status),
Err(err) => write!(resources.UART, "[CAN_1] receive failed: {:?}\r\n", err),
},
}
.unwrap();
}
};