CH32V203的一些踩坑记录

前言

CH32V203是沁恒推出的一款RISCV单片机,使用了他们自己开发的青稞内核,沁恒之前还做过ARM单片机,可能比较小众,并没有怎么听过,对沁恒的认知更多的是他们制作的一些接口芯片,例如CH340之类的串口芯片。

沁恒以V和F来区分RISCV和ARM内核的产品,当然还有一些CH57x、CH58x之类的蓝牙芯片,内核也是使用的RISCV。

沁恒提供了这些MCU的例程里包括了FreeRTOS,TencentOS、HarmonyOS、RT-Thread,我主要使用FreeRTOS,其他的操作系统没有怎么了解过,而沁恒没有自己提供IDE,而是一家叫做MountRiver Studio的工作室提供的IDE(魔改Esclipse)和工具链,工具链是GCC,但是他们修改了GCC,其实按GPL协议,他们应该开源自己的GCC,但是并没有,还有被修改的OpenOCD,沁恒也没有开源,非常的让人疑惑。

踩到的坑

中断声明时奇怪的定义

上文提到了GCC被修改了,修改的主要目的就是加入沁恒定义的硬件压栈声明,像是下面提供的这样。

void HardFault_Handler(void) __attribute__((interrupt()));	//软件压栈

void USART1_IRQHandler(void)__attribute__((interrupt( wch-interrupt-fast )));	//硬件压栈

非常奇怪的声明,想要搞清楚这些,必须去看沁恒的青稞内核手册。

里面提到了使用硬件压栈的时候需要这样声明,但是这个硬件压栈因为未知原因,可能会导致错误。

我在CH32V303和CH32V203上都开启过硬件压栈测试,可能是因为FreeRTOS或者其他原因,使用硬件压栈会在203上出错。

里面是有提到OS一般使用软件堆栈,还有不同的内核压栈数不太一样,如果不是对时间特别敏感,应该可以都走软件压栈吧?对时钟周期要求不是太高的情况下。

RISCV的特权模式以及浮点单元?

我对CPU内核了解的内容很少,现在大概知道是RISCV有几个模式,用户模式,监督模式,机器模式,其中机器模式的权限是最高的,用户模式的权限是最低的,FreeRTOS适配的RISCV是直接运行在机器模式上的,在移植RTOS的时候需要注意一下这点,所以我们需要让MCU保持在机器模式。

这里是官方的CH32V203 RTOS例程里的Startup File里定义的Mstatus寄存器初始值,其中只定义了MPP寄存器的值为0x03。

I2C发送地址的奇妙函数

/*********************************************************************
 * @fn      I2C_Send7bitAddress
 *
 * @brief   Transmits the address byte to select the slave device.
 *
 * @param   I2Cx - where x can be 1 or 2 to select the I2C peripheral.
 *          Address - specifies the slave address which will be transmitted.
 *          I2C_Direction - specifies whether the I2C device will be a
 *        Transmitter or a Receiver.
 *            I2C_Direction_Transmitter - Transmitter mode.
 *            I2C_Direction_Receiver - Receiver mode.
 *
 * @return  none
 */
void I2C_Send7bitAddress(I2C_TypeDef *I2Cx, uint8_t Address, uint8_t I2C_Direction)
{
    if(I2C_Direction != I2C_Direction_Transmitter)
    {
        Address |= OADDR1_ADD0_Set;
    }
    else
    {
        Address &= OADDR1_ADD0_Reset;
    }

    I2Cx->DATAR = Address;
}

奇妙的函数,我不知道沁恒程序员写这玩意的时候精神状态是什么样的,Send7BitAddress,光看函数名我以为要我给一个7Bit的I2C地址呢,试了若干次,在怀疑硬件是否有问题,然后我点开了这个函数.....合着你Send的是8Bit Address,还|/&一下最后一位,来标志方向啊...... 那我要你干什么,为什么我不自己构造呢?

未完待续,什么时候有空了上来再写点

魔改的OpenOCD没有开源,没有并入OpenOCD主线