Portapack应用开发教程 (十六) Debug程序 E max5864和spi实现

接下来可以看其它芯片了。

我仍然不打算看max2837和rffc507x,而是观察max5864芯片,它是adc/dac芯片,它在portapack固件里涉及的代码量很少,只有设置传输方向的功能。

可以看看firmware/application/hw/下面的max5864.cpp和max5864.hpp。

max5864.cpp文件里唯一只有这个set_mode函数

void MAX5864::set_mode(const Mode mode) {
	std::array<uint8_t, 1> command { toUType(mode) };
	_target.transfer(command.data(), command.size());
}

我感觉这个_target就有点类似之前iic芯片的bus的意思,相当于告诉程序你要操纵哪个芯片,只不过这次这个芯片不是iic总线,所以是target。

然后看看max5864.hpp


#include "spi_arbiter.hpp"

class MAX5864 {
public:
	constexpr MAX5864(
		spi::arbiter::Target& target
	) : _target(target)
	{
	}
}

我摘录了这么一段代码。这次max5864类的初始化函数里要传入的是spi::arbiter::target而不是之前的I2C& bus, I2C::address_t address了。

这个target应该同时包含了bus(主板上的某一个总线)和address(芯片在总线上的地址)。

另外引用的spi_arbiter.hpp也与i2c_pp.hpp对应,里面应该是spi总线的实现。

然后我们点开spi_arbiter.hpp,可以看到它也在引用spi_pp.hpp

#include "spi_pp.hpp"

namespace spi {
namespace arbiter {

class Arbiter {
public:
	constexpr Arbiter(
		SPI& bus
	) : _bus(bus),
		_config(nullptr)
	{
	}

	void transfer(const SPIConfig* const config, void* const data, const size_t count) {
		if( config != _config ) {
			_bus.stop();
			_bus.start(*config);
			_config = config;
		}
		_bus.transfer(data, count);
	}

private:
	SPI& _bus;
	const SPIConfig* _config;
};

class Target {
public:
	constexpr Target(
		Arbiter& arbiter,
		const SPIConfig& config
	) : _arbiter(arbiter),
		_config(config)
	{
	}

	void transfer(void* const data, const size_t count) {
		_arbiter.transfer(&_config, data, count);
	}

private:
	Arbiter& _arbiter;
	const SPIConfig _config;
};

} /* arbiter */
} /* spi */

芯片调用的是target的transfer函数,也就是下面的这个,然后这个函数又调用了arbiter的transfer函数(也就是上面那个transfer函数),最终调用了bus里的transfer函数。而现在的这个bus是开头声明的SPI& bus。
所以spi_arbiter.hpp主要只是一层封装,具体实现还是在spi_pp.cpp和spi_pp.hpp里,与iic的实现文件命名方式是一样的。

有一点要注意,arbiter的transfer函数里除了调用指定的bus的transfer函数以外,还根据前面传过来的config,配置了bus。

接下来,打开spi_pp.cpp发现里面没什么东西,主要都在spi_pp.hpp里。

	void start(const SPIConfig& config) {
		spiStart(_driver, &config);
	}

	void transfer(void* const data, const size_t count) {
		spiAcquireBus(_driver);
		spiSelect(_driver);
		spiExchange(_driver, count, data, data);
		spiUnselect(_driver);
		spiReleaseBus(_driver);
	}

摘录了一部分代码,这个start函数,可以对程序指定的spi bus做设置,设置完了才调用spiStart启动。下面的transfer函数就是被spi_arbiter调用的最里层的transfer函数,它针对的是芯片初始化时指定的总线来操作的。里面的spiAcquireBus和spiReleaseBus跟之前iic的函数命名方式也是对应的。

 

那么这个max5864芯片的初始化工作是在哪里实现的呢?

firmware/application/radio.cpp

static constexpr SPIConfig ssp_config_max5864 = {
	.end_cb = NULL,
	.ssport = gpio_max5864_select.port(),
	.sspad = gpio_max5864_select.pad(),
	.cr0 =
		  CR0_CLOCKRATE(ssp_scr(ssp1_pclk_f, ssp1_cpsr, max5864_spi_f))
		| CR0_FRFSPI
		| CR0_DSS8BIT
		,
	.cpsr = ssp1_cpsr,
};

static spi::arbiter::Arbiter ssp1_arbiter(portapack::ssp1);

static spi::arbiter::Target ssp1_target_max5864 {
	ssp1_arbiter,
	ssp_config_max5864
};

static max5864::MAX5864 baseband_codec { ssp1_target_max5864 };

最后一句话就是在初始化这个max5864类的对象,初始化的参数由ssp1_arbiter和ssp_config_max5864指定,它们分别是所选的总线以及芯片的一些设置。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值