Hi support team,
I'm trying to simulate the BDM protocol of the 9s12 chip series. Basically the protocol is as follows: Communication on 1 GPIO pin, output open-drain mode and input floating, clock base 5MHz.
Transmission of logic like picture below
Chapter 7 - BDM Serial Interface
Doing this work by writing the delay function (loops and commands _nop) with optimize O0 (the entire project is configured as O3).
To make sure the delay run time is exactly (which is important because the communication signal dose not have synchronize signal) must disable interrupt when making the transmission, I know that it is only prohibited interrupt below 6us, tranmit a bit of communication is only about 4us, everything is still under control.
static volatile uint8_t *GPIO = (uint8_t *)0x50000000UL; /*...............................................................................*/ static __inline void gpio_pin_write(uint8_t pin_num, uint8_t pin_level) { if (pin_level) *((uint32_t *)(GPIO + GPIO_PIN_OUTSET_OFFSET)) = 1 << pin_num; else *((uint32_t *)(GPIO + GPIO_PIN_OUTCLR_OFFSET)) = 1 << pin_num; } /*...............................................................................*/ static __inline void gpio_cfg_input(uint32_t pin_num) { NRF_GPIO_Type *reg = nrf_gpio_pin_port_decode(&pin_num); reg->PIN_CNF[pin_num] = ((uint32_t)NRF_GPIO_PIN_DIR_INPUT << GPIO_PIN_CNF_DIR_Pos) | ((uint32_t)NRF_GPIO_PIN_INPUT_CONNECT << GPIO_PIN_CNF_INPUT_Pos); } /* ============================== 9S12 Interface =============================== */ #pragma GCC push_options #pragma GCC optimize ("O0") static __inline void eeprom_9s12_delay_tc(uint32_t num) { uint32_t overflow = num * 4; /* Caculate clock cycle */ num = 0; while (num <= overflow) num += 4; /* Loop takes 4 clock cycles */ } #pragma GCC pop_options /*...............................................................................*/ #pragma GCC push_options #pragma GCC optimize ("O0") static void eeprom_9s12_send_cmd(uint8_t cmd, uint8_t ack) { nrf_gpio_cfg_output(EEPROM_9S12_BDM_PIN); for (uint8_t i = 0; i < 8; i++) { __disable_irq(); if (cmd & 0x80) { gpio_pin_write(EEPROM_9S12_BDM_PIN, 0); eeprom_9s12_delay_tc(4); gpio_pin_write(EEPROM_9S12_BDM_PIN, 1); eeprom_9s12_delay_tc(12); } else { gpio_pin_write(EEPROM_9S12_BDM_PIN, 0); eeprom_9s12_delay_tc(12); gpio_pin_write(EEPROM_9S12_BDM_PIN, 1); eeprom_9s12_delay_tc(4); } __enable_irq(); cmd = cmd << 1; } if (ack) { gpio_cfg_input(EEPROM_9S12_BDM_PIN); nrf_delay_us(25); } } #pragma GCC pop_options /*...............................................................................*/ #pragma GCC push_options #pragma GCC optimize ("O0") static uint8_t eeprom_9s12_rx(void) { uint8_t byte = 1; __disable_irq(); nrf_gpio_cfg_output(EEPROM_9S12_BDM_PIN); gpio_pin_write(EEPROM_9S12_BDM_PIN, 0); gpio_cfg_input(EEPROM_9S12_BDM_PIN); byte = nrf_gpio_pin_read(EEPROM_9S12_BDM_PIN); eeprom_9s12_delay_tc(12); __enable_irq(); return byte; } #pragma GCC pop_options
SoftDevice clock source as below//========================================================== // <o> NRF_SDH_CLOCK_LF_SRC - SoftDevice clock source. // <0=> NRF_CLOCK_LF_SRC_RC // <1=> NRF_CLOCK_LF_SRC_XTAL // <2=> NRF_CLOCK_LF_SRC_SYNTH #ifndef NRF_SDH_CLOCK_LF_SRC #define NRF_SDH_CLOCK_LF_SRC 1 #endif // <o> NRF_SDH_CLOCK_LF_RC_CTIV - SoftDevice calibration timer interval. #ifndef NRF_SDH_CLOCK_LF_RC_CTIV #define NRF_SDH_CLOCK_LF_RC_CTIV 0 #endif // <o> NRF_SDH_CLOCK_LF_RC_TEMP_CTIV - SoftDevice calibration timer interval under constant temperature. // <i> How often (in number of calibration intervals) the RC oscillator shall be calibrated // <i> if the temperature has not changed. #ifndef NRF_SDH_CLOCK_LF_RC_TEMP_CTIV #define NRF_SDH_CLOCK_LF_RC_TEMP_CTIV 0 #endif // <o> NRF_SDH_CLOCK_LF_ACCURACY - External clock accuracy used in the LL to compute timing. // <0=> NRF_CLOCK_LF_ACCURACY_250_PPM // <1=> NRF_CLOCK_LF_ACCURACY_500_PPM // <2=> NRF_CLOCK_LF_ACCURACY_150_PPM // <3=> NRF_CLOCK_LF_ACCURACY_100_PPM // <4=> NRF_CLOCK_LF_ACCURACY_75_PPM // <5=> NRF_CLOCK_LF_ACCURACY_50_PPM // <6=> NRF_CLOCK_LF_ACCURACY_30_PPM // <7=> NRF_CLOCK_LF_ACCURACY_20_PPM // <8=> NRF_CLOCK_LF_ACCURACY_10_PPM // <9=> NRF_CLOCK_LF_ACCURACY_5_PPM // <10=> NRF_CLOCK_LF_ACCURACY_2_PPM // <11=> NRF_CLOCK_LF_ACCURACY_1_PPM #ifndef NRF_SDH_CLOCK_LF_ACCURACY #define NRF_SDH_CLOCK_LF_ACCURACY 7 #endif
I was able to communicate to 9s12, read data from eeprom. But when compared to the original file, I discovered that there were several randomly wrong bytes, This means that something has impacted the delay time when transmitting.
I tested on my board, or with nrf52840DK, got the same problem. Had try to change calibration timer interval to 8s, 0.5 degree but got same issue.
I was not able to fix this issue. maybe it come from the hardware? Do you have any suggestions for the cause? Any suggestion is appreciated.
Sorry my English is not good, I used Translate to post the question.