| 
 
中级会员  
 
	积分354金钱354 注册时间2018-9-14在线时间157 小时 | 
 
 
 楼主|
发表于 2020-12-25 16:52:03
|
显示全部楼层 
| 本帖最后由 sppz 于 2020-12-26 11:06 编辑 
 记录下一些细节
 1.I2C引脚需要设置为开漏.
 2.AP3216C可以在远高于400K的情况下运行(虽然手册上说是400K).
 
 
 记录下整个main文件
 
 复制代码import px.base_object;
import px.cpu.stm32mp157.RCC;
import px.cpu.stm32mp157.GPIO;
import px.cpu.stm32mp157.USART;
import px.cpu.stm32mp157.GIC;
import px.cpu.stm32mp157.TIM;
import px.cpu.stm32mp157.EXTI;
import px.cpu.stm32mp157.I2C;
using namespace px_namespace;
using namespace px_namespace::cpu::stm32mp157;
static void reset_clock() noexcept
{
    // clock use HSI
    {
        auto ocensetr(RCC::OCENSETR());
        ocensetr.HSION() = 1;
        ocensetr.push();
        for (auto ocrdyr(RCC::OCRDYR()); ocrdyr.HSIRDY() == 0; ocrdyr.pull()) {}
        auto hsicfgr(RCC::HSICFGR());
        hsicfgr.HSIDIV() = 0;
        hsicfgr.push();
        for (auto ocrdyr(RCC::OCRDYR()); ocrdyr.HSIDIVRDY() == 0; ocrdyr.pull()) {}
        auto mpckselr(RCC::MPCKSELR());
        mpckselr.MPUSRC() = 0;
        mpckselr.push();
        do { mpckselr.pull(); } while (mpckselr.MPUSRCRDY() == 0);
        auto axidivr(RCC::AXIDIVR());
        axidivr.AXIDIV() = 0;
        axidivr.push();
        do { axidivr.pull(); } while (axidivr.AXIDIVRDY() == 0);
        auto assckselr(RCC::ASSCKSELR());
        assckselr.AXISSRC() = 0;
        assckselr.push();
        do { assckselr.pull(); } while (assckselr.AXISSRCRDY() == 0);
        auto mcudivr(RCC::MCUDIVR());
        mcudivr.MCUDIV() = 0;
        mcudivr.push();
        do { mcudivr.pull(); } while (mcudivr.MCUDIVRDY() == 0);
        auto mssckselr(RCC::MSSCKSELR());
        mssckselr.MCUSSRC() = 0;
        mssckselr.push();
        do { mssckselr.pull(); } while (mssckselr.MCUSSRCRDY() == 0);
    }
    // close PLLs
    {
        auto pll1cr(RCC::PLL1CR());
        pll1cr.DIVPEN() = 0;
        pll1cr.DIVQEN() = 0;
        pll1cr.DIVREN() = 0;
        pll1cr.push();
        pll1cr.PLLON() = 0;
        pll1cr.push();
        do { pll1cr.pull(); } while (pll1cr.PLL1RDY() == 1);
        auto pll2cr(RCC::PLL2CR());
        pll2cr.DIVPEN() = 0;
        pll2cr.DIVQEN() = 0;
        pll2cr.DIVREN() = 0;
        pll2cr.push();
        pll2cr.PLLON() = 0;
        pll2cr.push();
        do { pll2cr.pull(); } while (pll2cr.PLL2RDY() == 1);
        auto pll3cr(RCC::PLL3CR());
        pll3cr.DIVPEN() = 0;
        pll3cr.DIVQEN() = 0;
        pll3cr.DIVREN() = 0;
        pll3cr.push();
        pll3cr.PLLON() = 0;
        pll3cr.push();
        do { pll3cr.pull(); } while (pll3cr.PLL3RDY() == 1);
        auto pll4cr(RCC::PLL4CR());
        pll4cr.DIVPEN() = 0;
        pll4cr.DIVQEN() = 0;
        pll4cr.DIVREN() = 0;
        pll4cr.push();
        pll4cr.PLLON() = 0;
        pll4cr.push();
        do { pll4cr.pull(); } while (pll4cr.PLL4RDY() == 1);
    }
}
// MPU[PLL1_P] 600Mhz, AXI[PLL2_P] 266.5Mhz(reference Using the SSCG block), DDR[PLL2_R] 533Mhz, , MCU 200Mhz, APB[1-5] 100Mhz
static void set_clock() noexcept
{
    // open HSE
    {
        auto ocensetr(RCC::OCENSETR());
        ocensetr.HSEON();
        ocensetr.push();
        for (auto ocrdyr(RCC::OCRDYR()); ocrdyr.HSERDY() == 0; ocrdyr.pull()) {}
    }
    // PLLs source select
    {
        auto rck12selr(RCC::RCK12SELR());
        rck12selr.PLL12SRC() = 1;
        rck12selr.push();
        do { rck12selr.pull(); } while (rck12selr.PLL12SRCRDY() == 0);
        auto rck3selr(RCC::RCK3SELR());
        rck3selr.PLL3SRC() = 1;
        rck3selr.push();
        do { rck3selr.pull(); } while (rck3selr.PLL3SRCRDY() == 0);
    }
    // PLL1 set
    {
        auto pll1cfgr1(RCC::PLL1CFGR1());
        pll1cfgr1.DIVN() = 49;
        pll1cfgr1.DIVM1() = 1;
        pll1cfgr1.push();
        auto pll1cfgr2(RCC::PLL1CFGR2());
        pll1cfgr2.DIVP() = 0;
        pll1cfgr2.push();
        auto pll1fracr(RCC::PLL1FRACR());
        pll1fracr.FRACV() = 0;
        pll1fracr.FRACLE() = 0;
        pll1fracr.push();
        pll1fracr.FRACLE() = 1;
        pll1fracr.push();
        auto pll1cr(RCC::PLL1CR());
        pll1cr.SSCG_CTRL() = 0;
        pll1cr.PLLON() = 1;
        pll1cr.push();
        do { pll1cr.pull(); } while (pll1cr.PLL1RDY() == 0);
        pll1cr.DIVPEN() = 1;
        pll1cr.push();
    }
    // PLL2 set
    {
        auto pll2cfgr1(RCC::PLL2CFGR1());
        pll2cfgr1.DIVN() = 43;
        pll2cfgr1.DIVM2() = 1;
        pll2cfgr1.push();
        auto pll2cfgr2(RCC::PLL2CFGR2());
        pll2cfgr2.DIVP() = 1;
        pll2cfgr2.DIVR() = 0;
        pll2cfgr2.push();
        auto pll2fracr(RCC::PLL2FRACR());
        pll2fracr.FRACV() = 0;
        pll2fracr.FRACLE() = 0;
        pll2fracr.push();
        pll2fracr.FRACLE() = 1;
        pll2fracr.push();
        auto pll2csgr(RCC::PLL2CSGR());
        pll2csgr.MOD_PER() = 120;
        pll2csgr.SSCG_MODE() = 1;
        pll2csgr.INC_STEP() = 12;
        pll2csgr.push();
        auto pll2cr(RCC::PLL2CR());
        pll2cr.SSCG_CTRL() = 1;
        pll2cr.PLLON() = 1;
        pll2cr.push();
        do { pll2cr.pull(); } while (pll2cr.PLL2RDY() == 0);
        pll2cr.DIVPEN() = 1;
        pll2cr.DIVREN() = 1;
        pll2cr.push();
    }
    // PLL3 set
    {
        auto pll3cfgr1(RCC::PLL3CFGR1());
        pll3cfgr1.DIVN() = 49;
        pll3cfgr1.DIVM3() = 2;
        pll3cfgr1.IFRGE() = 1;
        pll3cfgr1.push();
        auto pll3cfgr2(RCC::PLL3CFGR2());
        pll3cfgr2.DIVP() = 1;
        pll3cfgr2.push();
        auto pll3fracr(RCC::PLL3FRACR());
        pll3fracr.FRACV() = 0;
        pll3fracr.FRACLE() = 0;
        pll3fracr.push();
        pll3fracr.FRACLE() = 1;
        pll3fracr.push();
        auto pll3cr(RCC::PLL3CR());
        pll3cr.PLLON() = 1;
        pll3cr.push();
        do { pll3cr.pull(); } while (pll3cr.PLL3RDY() == 0);
        pll3cr.DIVPEN() = 1;
        pll3cr.push();
    }
    // MCU set
    {
        auto mcudivr(RCC::MCUDIVR());
        mcudivr.MCUDIV() = 0;
        mcudivr.push();
        do { mcudivr.pull(); } while (mcudivr.MCUDIVRDY() == 0);
    }
    // AXI set
    {
        auto axidivr(RCC::AXIDIVR());
        axidivr.AXIDIV() = 0;
        axidivr.push();
        do { axidivr.pull(); } while (axidivr.AXIDIVRDY() == 0);
    }
    // APB4 set
    {
        auto apb4divr(RCC::APB4DIVR());
        apb4divr.APB4DIV() = 1;
        apb4divr.push();
        do { apb4divr.pull(); } while (apb4divr.APB4DIVRDY() == 0);
    }
    // APB5
    {
        auto apb5divr(RCC::APB5DIVR());
        apb5divr.APB5DIV() = 1;
        apb5divr.push();
        do { apb5divr.pull(); } while (apb5divr.APB5DIVRDY() == 0);
    }
    // APB1
    {
        auto apb1divr(RCC::APB1DIVR());
        apb1divr.APB1DIV() = 1;
        apb1divr.push();
        do { apb1divr.pull(); } while (apb1divr.APB1DIVRDY() == 0);
    }
    // APB2
    {
        auto apb2divr(RCC::APB2DIVR());
        apb2divr.APB2DIV() = 1;
        apb2divr.push();
        do { apb2divr.pull(); } while (apb2divr.APB2DIVRDY() == 0);
    }
    // APB3
    {
        auto apb3divr(RCC::APB3DIVR());
        apb3divr.APB3DIV() = 1;
        apb3divr.push();
        do { apb3divr.pull(); } while (apb3divr.APB3DIVRDY() == 0);
    }
    // switch
    {
        auto mpckselr(RCC::MPCKSELR());
        mpckselr.MPUSRC() = 2; // pll1_p_ck
        mpckselr.push();
        do { mpckselr.pull(); } while (mpckselr.MPUSRCRDY() == 0);
        auto assckselr(RCC::ASSCKSELR());
        assckselr.AXISSRC() = 2; // pll2_p_ck
        assckselr.push();
        do { assckselr.pull(); } while (assckselr.AXISSRCRDY() == 0);
        auto mssckselr(RCC::MSSCKSELR());
        mssckselr.MCUSSRC() = 3; // pll3_p_ck
        mssckselr.push();
        do { mssckselr.pull(); } while (mssckselr.MCUSSRCRDY() == 0);
    }
}
static void initialize_clock() noexcept
{
    reset_clock();
    set_clock();
}
static void initialize_gic() noexcept
{
    //38 EXTI0, 41 EXTI3, 84 uart4, 86 tim6, 97 EXTI7
    auto igroupr(GICD::IGROUPR(38)); igroupr.GROUP_STATUS() = 1;
    igroupr.index(41); igroupr.GROUP_STATUS() = 1;
    igroupr.index(84); igroupr.GROUP_STATUS() = 1;
    igroupr.index(86); igroupr.GROUP_STATUS() = 1;
    igroupr.index(97); igroupr.GROUP_STATUS() = 1;
    igroupr.push();
    auto isenabler(GICD::ISENABLER(38)); isenabler.SET_ENABLE() = 1;
    isenabler.index(41); isenabler.SET_ENABLE() = 1;
    isenabler.index(84); isenabler.SET_ENABLE() = 1;
    isenabler.index(86); isenabler.SET_ENABLE() = 1;
    isenabler.index(97); isenabler.SET_ENABLE() = 1;
    isenabler.push();
    auto ipriorityr(GICD::IPRIORITYR(38)); ipriorityr.PRIORITY() = 0;
    ipriorityr.index(41); ipriorityr.PRIORITY() = 0;
    ipriorityr.index(84); ipriorityr.PRIORITY() = 0;
    ipriorityr.index(86); ipriorityr.PRIORITY() = 0;
    ipriorityr.index(97); ipriorityr.PRIORITY() = 0;
    ipriorityr.push();
    auto itargetsr(GICD::ITARGETSR(38)); itargetsr.CPU_TARGETS() = 1;
    itargetsr.index(41); itargetsr.CPU_TARGETS() = 1;
    itargetsr.index(84); itargetsr.CPU_TARGETS() = 1;
    itargetsr.index(86); itargetsr.CPU_TARGETS() = 1;
    itargetsr.index(97); itargetsr.CPU_TARGETS() = 1;
    itargetsr.push();
    auto icfgr(GICD::ICFGR(38)); icfgr.INT_CONFIG() = 3;
    icfgr.index(41); icfgr.INT_CONFIG() = 3;
    icfgr.index(84); icfgr.INT_CONFIG() = 1;
    icfgr.index(86); icfgr.INT_CONFIG() = 1;
    icfgr.index(97); icfgr.INT_CONFIG() = 3;
    icfgr.push();
}
void initialize_exti() noexcept
{
    // PA.0 WK_UP, PG.3 KEY0, PH.7 KEY1
    auto rtsr(EXTI::RTSR(0)); rtsr.RT() = 1;
    rtsr.index(3); rtsr.RT() = 1;
    rtsr.index(7); rtsr.RT() = 1;
    rtsr.push();
    auto ftsr(EXTI::FTSR(0)); ftsr.FT() = 1;
    ftsr.index(3); ftsr.FT() = 1;
    ftsr.index(7); ftsr.FT() = 1;
    ftsr.push();
    auto exticr(EXTI::EXTICR(0)); exticr.EXTI() = 0;
    exticr.index(3); exticr.EXTI() = 6;
    exticr.index(7); exticr.EXTI() = 7;
    exticr.push();
    auto imr(EXTI::IMR(0)); imr.IM() = 1;
    imr.index(3); imr.IM() = 1;
    imr.index(7); imr.IM() = 1;
    imr.push();
    auto emr(EXTI::EMR(0)); emr.EM() = 1;
    emr.index(3); emr.EM() = 1;
    emr.index(7); emr.EM() = 1;
    emr.push();
}
static void initialize_gpio() noexcept
{
    // open GPIO[A, B, F, G, H, I]
    {
        auto mp_ahb4ensetr(RCC::MP_AHB4ENSETR());
        mp_ahb4ensetr.GPIOAEN() = 1;
        mp_ahb4ensetr.GPIOBEN() = 1;
        mp_ahb4ensetr.GPIOFEN() = 1;
        mp_ahb4ensetr.GPIOGEN() = 1;
        mp_ahb4ensetr.GPIOHEN() = 1;
        mp_ahb4ensetr.GPIOIEN() = 1;
        mp_ahb4ensetr.push();
    }
    { // A.0 WK_UP, A.11 I2C6_SCL, A.12 I2C6_SDA
        auto moder(GPIOA::MODER(0)); moder.MODE() = 0;
        moder.index(11); moder.MODE() = 2;
        moder.index(12); moder.MODE() = 2;
        moder.push();
        auto otyper(GPIOA::OTYPER(0)); otyper.OT() = 0;
        otyper.index(11); otyper.OT() = 1; // 一定要是开漏!!!
        otyper.index(12); otyper.OT() = 1; // 一定要是开漏!!!
        otyper.push();
        auto ospeedr(GPIOA::OSPEEDR(0)); ospeedr.OS() = 0;
        ospeedr.index(11); ospeedr.OS() = 3;
        ospeedr.index(12); ospeedr.OS() = 3;
        ospeedr.push();
        auto pupdr(GPIOA::PUPDR(0)); pupdr.PUPD() = 2;
        pupdr.index(11); pupdr.PUPD() = 0;
        pupdr.index(12); pupdr.PUPD() = 0;
        pupdr.push();
        auto afr(GPIOA::AFR(0)); afr.AF() = 0;
        afr.index(11); afr.AF() = 2;
        afr.index(12); afr.AF() = 2;
        afr.push();
    }
    { // B.2 UART4_RX
        auto moder(GPIOB::MODER(2)); moder.MODE() = 2;
        moder.push();
        auto otyper(GPIOB::OTYPER(2)); otyper.OT() = 0;
        otyper.push();
        auto ospeedr(GPIOB::OSPEEDR(2)); ospeedr.OS() = 3;
        ospeedr.push();
        auto pupdr(GPIOB::PUPDR(2)); pupdr.PUPD() = 1;
        pupdr.push();
        auto afr(GPIOB::AFR(2)); afr.AF() = 8;
        afr.push();
    }
    { // F.3 led
        auto moder(GPIOF::MODER(3)); moder.MODE() = 1;
        moder.push();
        auto otyper(GPIOF::OTYPER(3)); otyper.OT() = 0;
        otyper.push();
        auto ospeedr(GPIOF::OSPEEDR(3)); ospeedr.OS() = 0;
        ospeedr.push();
        auto pupdr(GPIOF::PUPDR(3)); pupdr.PUPD() = 1;
        pupdr.push();
        auto odr(GPIOF::ODR(3)); odr.OD() = 1;
        odr.push();
    }
    { // G.3 KEY0, G.11 UART4_TX
        auto moder(GPIOG::MODER(3)); moder.MODE() = 0;
        moder.index(11); moder.MODE() = 2;
        moder.push();
        auto otyper(GPIOG::OTYPER(3)); otyper.OT() = 0;
        otyper.index(11); otyper.OT() = 0;
        otyper.push();
        auto ospeedr(GPIOG::OSPEEDR(3)); ospeedr.OS() = 0;
        ospeedr.index(11); ospeedr.OS() = 3;
        ospeedr.push();
        auto pupdr(GPIOG::PUPDR(3)); pupdr.PUPD() = 1;
        pupdr.index(11); pupdr.PUPD() = 1;
        pupdr.push();
        auto afr(GPIOG::AFR(3)); afr.AF() = 0;
        afr.index(11); afr.AF() = 6;
        afr.push();
    }
    { // H.7 KEY1
        auto moder(GPIOH::MODER(7)); moder.MODE() = 0;
        moder.push();
        auto otyper(GPIOH::OTYPER(7)); otyper.OT() = 0;
        otyper.push();
        auto ospeedr(GPIOH::OSPEEDR(7)); ospeedr.OS() = 0;
        ospeedr.push();
        auto pupdr(GPIOH::PUPDR(7)); pupdr.PUPD() = 1;
        pupdr.push();
        auto afr(GPIOH::AFR(7)); afr.AF() = 0;
        afr.push();
    }
    { // I.0 led
        auto moder(GPIOI::MODER(0)); moder.MODE() = 1;
        moder.push();
        auto otyper(GPIOI::OTYPER(0)); otyper.OT() = 0;
        otyper.push();
        auto ospeedr(GPIOI::OSPEEDR(0)); ospeedr.OS() = 0;
        ospeedr.push();
        auto pupdr(GPIOI::PUPDR(0)); pupdr.PUPD() = 1;
        pupdr.push();
        auto odr(GPIOI::ODR(0)); odr.OD() = 0;
        odr.push();
    }
    // // test I2C6
    // {
    //     auto mp_ahb5ensetr(RCC::MP_AHB5ENSETR());
    //     mp_ahb5ensetr.GPIOZEN() = 1;
    //     mp_ahb5ensetr.push();
    // }
    // { // Z.6 I2C6_SCL, Z.7 I2C6_SDA
    //     auto moder(GPIOZ::MODER(6)); moder.MODE() = 2;
    //     moder.index(7); moder.MODE() = 2;
    //     moder.push();
    //     auto otyper(GPIOZ::OTYPER(6)); otyper.OT() = 0;
    //     otyper.index(7); otyper.OT() = 0;
    //     otyper.push();
    //     auto ospeedr(GPIOZ::OSPEEDR(6)); ospeedr.OS() = 3;
    //     ospeedr.index(7); ospeedr.OS() = 3;
    //     ospeedr.push();
    //     auto pupdr(GPIOZ::PUPDR(6)); pupdr.PUPD() = 1;
    //     pupdr.index(7); pupdr.PUPD() = 1;
    //     pupdr.push();
    //     auto afr(GPIOZ::AFR(6)); afr.AF() = 2;
    //     afr.index(7); afr.AF() = 2;
    //     afr.push();
    // }
}
static void initialize_uart4() noexcept
{
    auto apb1rstsetr(RCC::APB1RSTSETR());
    apb1rstsetr.UART4RST() = 1;
    apb1rstsetr.push();
    auto apb1rstclrr(RCC::APB1RSTCLRR());
    while (apb1rstclrr.UART4RST() == 0) { apb1rstclrr.pull(); }
    apb1rstclrr.UART4RST() = 1;
    apb1rstclrr.push();
    do { apb1rstclrr.pull(); } while (apb1rstclrr.UART4RST() == 1);
    auto uart24ckselr(RCC::UART24CKSELR());
    uart24ckselr.UART24SRC() = 0;
    uart24ckselr.push();
    auto mp_apb1ensetr(RCC::MP_APB1ENSETR());
    mp_apb1ensetr.UART4EN() = 1;
    mp_apb1ensetr.push();
    auto prescr(UART4::PRESCR());
    prescr.PRESC() = 0;
    prescr.push();
    auto brr(UART4::BRR());
    brr.BR() = 100000000 / 115200;
    brr.push();
    auto cr1(UART4::CR1());
    cr1.UE() = 1;
    cr1.RE() = 1;
    cr1.TE() = 1;
    cr1.RXNEIE() = 1;
    cr1.M0() = 0;
    cr1.OVER8() = 0;
    cr1.M1() = 0;
    cr1.push();
}
static void initialize_i2c6() noexcept // clock default use apb5
{
    auto mp_apb5ensetr(RCC::MP_APB5ENSETR());
    mp_apb5ensetr.I2C6EN() = 1;
    mp_apb5ensetr.push();
    auto cr1(I2C6::CR1());
    cr1.ANFOFF() = 1;
    cr1.DNF() = 0;
    cr1.NOSTRETCH() = 0;
    cr1.push();
    auto cr2(I2C6::CR2());
    cr2.PECBYTE() = 0;
    cr2.push();
    // 
    auto timingr(I2C6::TIMINGR());
    timingr.PRESC() = 5;
    timingr.SCLL() = 24;
    timingr.SCLH() = 24;
    timingr.SDADEL() = 25;
    timingr.SCLDEL() = 24;
    timingr.push();
    cr1.pull();
    cr1.PE() = 1;
    cr1.push();
}
static void initialize_tim6() noexcept
{
    // 根据157 reference-568页,当前配置下TIM的频率为200Mhz
    auto mp_apb1ensetr(RCC::MP_APB1ENSETR());
    mp_apb1ensetr.TIM6EN() = 1;
    mp_apb1ensetr.push();
    auto cr2(TIM6::CR2());
    cr2.MMS() = 0;
    cr2.push();
    auto dier(TIM6::DIER());
    dier.UIE() = 1;
    dier.UDE() = 0;
    dier.push();
    auto pscr(TIM6::PSCR());
    pscr.PSC() = 199;
    pscr.push();
    auto arr(TIM6::ARR());
    arr.AR() = 1000;
    arr.push();
    auto cr1(TIM6::CR1());
    cr1.CEN() = 1;
    cr1.UDIS() = 0;
    cr1.URS() = 0;
    cr1.OPM() = 0;
    cr1.ARPE() = 1;
    cr1.UIFREMAP() = 0;
    cr1.push();
}
void put_character(const character_type value) noexcept
{
    for (auto isr(UART4::ISR()); isr.TXE() == 0; isr.pull()) {}
    auto tdr(UART4::TDR(0));
    tdr.TD() = value;
    tdr.push();
}
void put_string(const character_type* value) noexcept
{
    while (*value != '\0')
    {
        put_character(*value);
        ++value;
    }
}
void put_size(const size& value) noexcept
{
    if (value < 10)
    {
        put_character('0' + value.value());
        return;
    }
    put_size(value / 10);
    put_character('0' + (value % 10).value());
}
static void i2c6_write1(unsigned_integer8 address, unsigned_integer8 data) noexcept
{
    auto isr(I2C6::ISR());
    while (isr.BUSY() == 1) { isr.pull(); };
    auto cr2(I2C6::CR2());
    cr2.SADD() = address;
    cr2.RD_WRN() = 0;
    cr2.ADD10() = 0;
    cr2.NBYTES() = 1;
    cr2.RELOAD() = 0;
    cr2.AUTOEND() = 1;
    cr2.START()  = 1;
    cr2.push();
    do { isr.pull(); } while (isr.TXE() == 0);
    auto txdr(I2C6::TXDR(data));
    txdr.push();
}
static void i2c6_write2(unsigned_integer8 address, unsigned_integer8 data0, unsigned_integer8 data1) noexcept
{
    auto isr(I2C6::ISR());
    while (isr.BUSY() == 1) { isr.pull(); };
    auto cr2(I2C6::CR2());
    cr2.SADD() = address;
    cr2.RD_WRN() = 0;
    cr2.ADD10() = 0;
    cr2.NBYTES() = 2;
    cr2.RELOAD() = 0;
    cr2.AUTOEND() = 1;
    cr2.START()  = 1;
    cr2.push();
    I2C6::TXDR_cache txdr;
    do { isr.pull(); } while (isr.TXE() == 0);
    txdr.TXDATA() = data0;
    txdr.push();
    do { isr.pull(); } while (isr.TXE() == 0);
    txdr.TXDATA() = data1;
    txdr.push();
}
static unsigned_integer8 i2c6_read(unsigned_integer8 address) noexcept
{
    auto isr(I2C6::ISR());
    while (isr.BUSY() == 1) { isr.pull(); };
    auto cr2(I2C6::CR2());
    cr2.SADD() = address;
    cr2.RD_WRN() = 1;
    cr2.ADD10() = 0;
    cr2.NBYTES() = 1;
    cr2.RELOAD() = 0;
    cr2.AUTOEND() = 1;
    cr2.START() = 1;
    cr2.push();
    do { isr.pull(); } while (isr.RXNE() == 0);
    auto rxdr(I2C6::RXDR());
    return rxdr.RXDATA();
}
static void ap3216c_write(unsigned_integer8 address, unsigned_integer8 data) noexcept
{
    i2c6_write2(0x1e << 1, address, data); // 注意7位地址时,使用的是bit[1..7]
}
static unsigned_integer8 ap3216c_read(unsigned_integer8 address) noexcept
{
    i2c6_write1(0x1e << 1, address); // 注意7位地址时,使用的是bit[1..7]
    return i2c6_read(0x1e << 1);
}
void initialize() noexcept
{
    initialize_clock();
    initialize_gpio();
    initialize_uart4();
    initialize_i2c6();
    initialize_tim6();
    initialize_gic();
    initialize_exti();
    put_string("boot.\r\n");
}
extern "C"
{
    void px_GIC_UART4() noexcept // 最简单的处理
    {
        auto isr(UART4::ISR());
        if (isr.RXNE() == 1)
        {
            put_character((character_type)UART4::RDR().RD());
        }
    }
    size systick_count(0);
    void px_GIC_TIM6() noexcept //
    {
        auto sr(TIM6::SR());
        sr.UIF() = 0;
        sr.push();
        ++systick_count;
        if (systick_count % 1000 == 0)
        {
            put_string("second=");
            put_size(systick_count / 1000);
            {
                auto odr(GPIOF::ODR(3)); odr.OD() ^= 1;
                odr.push();
            }
            put_string(" ap3216c");
            put_string(" mode[0x0]="); put_size(ap3216c_read(0x0));
            put_string(" PS_low[0xe]="); put_size(ap3216c_read(0xe));
            put_string(" PS_high[0xf]="); put_size(ap3216c_read(0xf));
            put_string("\r\n");
        }
    }
    void px_GIC_EXTI0() noexcept // WK_UP
    {
        auto rpr(EXTI::RPR(0));
        if (rpr.RPIF() == 1)
        {
            rpr.value() = 0;
            rpr.RPIF() = 1;
            rpr.push();
        }
        auto fpr(EXTI::FPR(0));
        if (fpr.FPIF() == 1)
        {
            fpr.value() = 0;
            fpr.FPIF() = 1;
            fpr.push();
        }
        put_string("WK_UP.\r\n");
    }
    void px_GIC_EXTI3() noexcept // KEY0
    {
        auto rpr(EXTI::RPR(3));
        if (rpr.RPIF() == 1)
        {
            rpr.value() = 0;
            rpr.RPIF() = 1;
            rpr.push();
        }
        auto fpr(EXTI::FPR(3));
        if (fpr.FPIF() == 1)
        {
            fpr.value() = 0;
            fpr.FPIF() = 1;
            fpr.push();
        }
        put_string("KEY0 open ap3216c.\r\n");
        ap3216c_write(0x0, 3);
    }
    void px_GIC_EXTI7() noexcept // KEY1
    {
        auto rpr(EXTI::RPR(7));
        if (rpr.RPIF() == 1)
        {
            rpr.value() = 0;
            rpr.RPIF() = 1;
            rpr.push();
        }
        auto fpr(EXTI::FPR(7));
        if (fpr.FPIF() == 1)
        {
            fpr.value() = 0;
            fpr.FPIF() = 1;
            fpr.push();
        }
        put_string("KEY1 close ap3216c.\r\n");
        ap3216c_write(0x0, 0);
    }
    void px_GIC_default() noexcept
    {
        put_string("GIC_default\r\n");
    }
}
 | 
 |