bootloader UART  流程分析

1 scuart_full_init 初始化 UART,初始化过程包含注册回调函数,当接收到数据时RX 接收引脚发生中断,调用回调函数 instance_transition_callback。

2 进入函数 scuart_poll_for_activity,主要是对 回调函数 instance_transition_callback 二次处理. 最终得到UART 波特率,使用得到的波特率重新初始化UART,

bootloader_initget_active_peripheralscuart_full_initautobaud_init(self->instance);void autobaud_init(uint32_t instance)
{s_transitionCount = 0;s_firstByteTotalTicks = 0;s_secondByteTotalTicks = 0;s_lastToggleTicks = 0;s_instanceMeasured = 0;s_ticksBetweenFailure = microseconds_convert_to_ticks(kMaximumTimeBetweenFallingEdges);enable_autobaud_pin_irq(instance, instance_transition_callback);
}//RX引脚将下降沿中断回调函数,每产生一个下降沿中断 会计算每一个下降沿时刻,并将相邻的两个下降沿事件
//差值保存在 s_ticksFallingEdges 数组里面;
void instance_transition_callback(uint32_t instance)
{uint64_t ticks = microseconds_get_ticks();s_transitionCount++;uint64_t delta = ticks - s_lastToggleTicks;// The last toggle was longer than we allow so treat this as the first oneif (delta > s_ticksBetweenFailure){s_transitionCount = 1;}switch (s_transitionCount){case 1:// This is our first falling edge, store the initial ticks temporarily in firstByteTicks// and save the instance that we are measurings_ticksAtFirstFallingEdge = ticks;s_firstByteTotalTicks = ticks;s_instanceMeasured = instance;break;case kFirstByteRequiredFallingEdges:// We reached the end of our measurable first byte, subtract the current ticks from the initial// first byte tickss_firstByteTotalTicks = ticks - s_firstByteTotalTicks;break;case (kFirstByteRequiredFallingEdges + 1):// We hit our first falling edge of the second byte, store the initial ticks temporarily in secondByteTickss_secondByteTotalTicks = ticks;break;case (kFirstByteRequiredFallingEdges + kSecondByteRequiredFallingEdges):// We reached the end of our measurable second byte, subtract the current ticks from the initial// second byte tickss_secondByteTotalTicks = ticks - s_secondByteTotalTicks;disable_autobaud_pin_irq(instance);break;}s_ticksFallingEdges[s_transitionCount - 1] = ticks - s_ticksAtFirstFallingEdge;//[7-1] = 15127s_lastToggleTicks = ticks;
}//注册UART RX 引脚下降沿中断函数
//Blhost 发送两个字节 0x5a 和 0xa5,RX引脚将产生7个下降沿中断。
void enable_autobaud_pin_irq(uint32_t instance, pin_irq_callback_t func)
{switch (instance){case 0:// Only look for a falling edge for our interruptsPORT_SetPinInterruptConfig(UART0_RX_PORT_BASE, UART0_RX_GPIO_PIN_NUM, kPORT_InterruptFallingEdge);NVIC_SetPriority(UART0_RX_GPIO_IRQn, PORT_IRQC_INTERRUPT_ENABLED_PRIORITY);NVIC_EnableIRQ(UART0_RX_GPIO_IRQn);s_pin_irq_func[0] = func;break;
...
}//RX引脚将下降沿中断
void UART0_RX_GPIO_IRQHandler(void)
{// Check if the pin for UART0 is what triggered the RX PORT interruptif (PORT_GetPinIsf(UART0_RX_PORT_BASE, UART0_RX_GPIO_PIN_NUM) && s_pin_irq_func[0]){s_pin_irq_func[0](0);PORT_ClearPinsInterruptFlags(UART0_RX_PORT_BASE, ~0U);}
}
scuart_full_init //uart初始化进入 while 循环 检测有效的UART 波特率scuart_poll_for_activitybool scuart_poll_for_activity(const peripheral_descriptor_t *self)
{uint32_t baud;status_t autoBaudCompleted = autobaud_get_rate(self->instance, &baud);if (autoBaudCompleted == kStatus_Success){uart_config_t userConfig;UART_Type *base = get_uart_baseAddr(self->instance);UART_GetDefaultConfig(&userConfig);userConfig.baudRate_Bps = baud;userConfig.enableTx = true;userConfig.enableRx = true;if (UART_Init(base, &userConfig, get_uart_clock(self->instance)) == kStatus_Success){UART_SetSystemIRQ(self->instance, kPeripheralEnableIRQ);UART_EnableInterrupts(base, kUART_RxDataRegFullInterruptEnable);// Configure selected pin as uart peripheral interfaceself->pinmuxConfig(self->instance, kPinmuxType_Peripheral);// This was the byte pattern identified in autobaud detection, inform the command layers_scuart_byte_receive_callback(kFramingPacketStartByte);s_scuart_byte_receive_callback(kFramingPacketType_Ping);g_uartInitDone = true;return true;}else{autobaud_init(self->instance);}}return false;
}

波形

/**   This function filters the invalid noises on LPUART rx pins by following characters:*   For 0x5A, the interval between falling edges meets 3:3:2*   For 0xA5, the interval between falling edges meets: 4:3*      |              0x5A                 |                 0xA6              |**   ___       ___     _____     ___     ______       _____       ___     ________*      | S 0 | 1 | 0 | 1 1 | 0 | 1 | 0 | STOP | S 0 | 1 1 | 0 0 | 1 | 0 | 1  STOP*       -----     ---       ---     ---        -----       -----     ---*   ---------------------------------------------------------------------------*      |    1st  |   2nd   |  3rd  |          |    1st    |    2nd  |*   ---------------------------------------------------------------------------*      |     3   :     3   :   2   |          |     4     :     3   |

波特率计算思虑

計算波特率思路 :K64 bootloader 主频48MHZ, 要产生57600 bit/s 波特率,每传送一位需要833.33个时钟周期,取833;如果已知主频时钟和每一位的时钟周期,则可以计算出 波特率。

Bhost 采用UART 发0x5A 和 0xA6 两个字节给Bootloader,测出这两个字节共需要12598 个clock, 共传输15位,即每一位需要840clock;波特率为 48000000 / 840 = 57142. (取57600)。

令人疑惑的是15是怎么来的,对于0x5A ,起始位start 加上第一个bit位到这个字节的最后一个下降沿之间的 7 个bit,即8; 对于0xA6,我们有起始位start +6位到最后下降沿=7位。

status_t autobaud_get_rate(uint32_t instance, uint32_t *rate)
{if ((s_transitionCount == (kFirstByteRequiredFallingEdges + kSecondByteRequiredFallingEdges)) &&(instance == s_instanceMeasured)){// Invalid bytes received.if (!is_falling_edge_interval_valid()){// Restart auto buad detectionautobaud_init(instance);return kStatus_Fail;}uint32_t calculatedBaud =(microseconds_get_clock() * (kNumberOfBitsForFirstByteMeasured + kNumberOfBitsForSecondByteMeasured)) /(uint32_t)(s_firstByteTotalTicks + s_secondByteTotalTicks);// Round the rate to the nearest step size// rounded = stepSize * (value/stepSize + .5)// multiplying by 10 since we can't work with floats// kAutobaudStepSize 为 1200,这个值是 57600 119200 38400 等常见波特率 公约数*rate = ((((calculatedBaud * 10) / kAutobaudStepSize) + 5) / 10) * kAutobaudStepSize;return kStatus_Success;}else{// no baud rate yet/inactivereturn kStatus_Fail;}
}

K64 计算 UART波特率相关推荐

  1. 【嵌入式】任意波特率的合理计算——高波特率、低误差

    文章目录 一.概要 二.STM32F4波特率的计算方法 三.高波特率.低误差的计算方法 四.实验验证 1.与参考手册中的典型波特率误差进行比对 2.实际验证 一.概要 使用UART串口时往往比较喜欢配 ...

  2. NXP JN5169 UART 波特率设置

    NXP JN5169 UART 波特率设置 一.系统时钟介绍 1.高速(32MHz)系统时钟 1.32MHz 晶体振荡器 2.高速RC振荡器 2.低速(32kHz)系统时钟 1.32 kHz RC 振 ...

  3. (100)Verilog HDL:UART波特率设计

    (100)Verilog HDL:UART波特率设计 1.1 目录 1)目录 2)FPGA简介 3)Verilog HDL简介 4)Verilog HDL:UART波特率设计 5)结语 1.2 FPG ...

  4. NXP JN5169 UART波特率问题

    被NXP JN5169的UART收数据大批量错误坑了一把,最后发现是NXP的速率计算因子误差太大导致. 写了个程序,把所有常见的波特率匹配了一把,匹配的结果(相对误差在千分之七以下)即波特率的计算因子 ...

  5. UART 波特率选择的认识与理解

    笔者前几天碰到了串口波特率的问题,想要1M以上的波特率,发现波特率总是乱码,常用标准的几种波特率也不是很好用. 1.UART时钟情况说明 ch340G模块,时钟为12MHZ. 某PMC开发板,ARM ...

  6. TMS320F28335 uart波特率参数设置

    结合自己调试的经验,这里做一个总结,uart的波特率参数需要通过计算来得到的,具体方法如下: void scic_echoback_init() {// Note: Clocks were turne ...

  7. (五)嵌入式:设置UART波特率并实现转变字符串大小,实现人机交互

    本次实验使用开发板是美国Marvell公司生产的SOHO级网络通信微处理器芯片88E6218.开发环境是Ubuntu12.04,内核是UCLinux. 1.使用串口 本次课程主要是了解uart的使用, ...

  8. DSP:TMS320C6657 之 UART波特率问题

    6657 设置串口波特率 以614400为例 (1)根据公式计算分频系数 (2)1GHz主频下 UART输入频率166666666Hz.(1/6) (3)16倍采样率下分频系数是16.95取整16,实 ...

  9. APB时钟计算串口波特率

    与APB计算定时器频率相似 同样在datasheet中查找串口使用的总线 STM32串口波特率通过USART_BRR进行设置 可以看到USART1挂在APB2,APB2总线的速率是84MHz 可以使用 ...

  10. 嵌入式 - 晶振频率的来源和UART波特率的选择

    电路板上经常要用到32.768KHz的晶振,表示晶振经过32768K个周期就是1s,16进制就是0x8000,是2的n次方形式,2^15. 这颗料已经出现了20年,非常普遍,也非常便宜,在各种电路中使 ...

最新文章

  1. win7mysql免安装版安装_win7下MySQL免安装版下载安装、配置与使用
  2. 小 Q 与函数求和 1(牛客练习赛 81 E)
  3. 【转】ABP源码分析二十三:Authorization
  4. 合肥注册公司(各区注册地点说明)
  5. linux 分配组命令,linux下一个用户如何分配给多个用户组?求命令,谢了。
  6. ajax常见的面试题
  7. echarts源码打包_Echarts源码阅读指南
  8. [10秒学会] - iOS录制屏幕 ReplayKit
  9. 解决响应式布局border带来的麻烦
  10. spring视频教程
  11. odoo stock库存模块
  12. mp c2011sp文件服务器,理光Ricoh MP C2011SP驱动
  13. hitb2017 sentosa writeup
  14. 第50篇-企查查请求头参数分析【2022-09-29】
  15. ESR-CMDS参数含义
  16. 排序算法系列之(二)——冒泡排序名字最为形象的一个
  17. 小白如何学3D建模?从零开始变大神
  18. 总结 离散数学知识点
  19. TCP四次挥手断开连接
  20. Halcon图像预处理-感兴趣区域(ROI)

热门文章

  1. 举个栗子~Tableau 技巧(225):制作事件节点时间轴
  2. 计算机病毒的历史:1986-1993(译文…
  3. Raspberry 静态IP配置
  4. 【愚公系列】2022年07月 Go教学课程 004-Go代码注释
  5. 双机热备软件 Pacemaker和Keepalived
  6. matlab 门函数频谱,时域门函数及门函数串的频谱分析
  7. python--字符串
  8. 分隔符中的分页符与分节符
  9. 从ghost映像.gho文件快速创建vmware虚拟机
  10. Dialog dismiss 失效的问题,