Compare commits
8 commits
master
...
circuitpyt
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
49c0c1613d | ||
|
|
218b3826a9 | ||
|
|
7a6660134a | ||
|
|
7142b366a6 | ||
|
|
f998690e65 | ||
|
|
b7e38276a7 | ||
|
|
9323b67fce | ||
|
|
12538a7c45 |
4 changed files with 30 additions and 5 deletions
|
|
@ -123,9 +123,7 @@ static void __no_inline_not_in_flash_func(flash_cs_force)(bool high) {
|
|||
);
|
||||
}
|
||||
|
||||
// May want to expose this at some point but this is unlikely to be the right
|
||||
// interface to do so. Keep it static
|
||||
static void __no_inline_not_in_flash_func(flash_do_cmd)(const uint8_t *txbuf, uint8_t *rxbuf, size_t count) {
|
||||
void __no_inline_not_in_flash_func(flash_do_cmd)(const uint8_t *txbuf, uint8_t *rxbuf, size_t count) {
|
||||
void (*connect_internal_flash)(void) = (void(*)(void))rom_func_lookup(rom_table_code('I', 'F'));
|
||||
void (*flash_exit_xip)(void) = (void(*)(void))rom_func_lookup(rom_table_code('E', 'X'));
|
||||
void (*flash_flush_cache)(void) = (void(*)(void))rom_func_lookup(rom_table_code('F', 'C'));
|
||||
|
|
|
|||
|
|
@ -80,6 +80,22 @@ void flash_range_program(uint32_t flash_offs, const uint8_t *data, size_t count)
|
|||
*/
|
||||
void flash_get_unique_id(uint8_t *id_out);
|
||||
|
||||
/*! \brief Execute bidirectional flash command
|
||||
* \ingroup hardware_flash
|
||||
*
|
||||
* Execute a bidirectional command to the flash. Bytes are simultaneously
|
||||
* transmitted and received. Therefore, both buffers must be the same length,
|
||||
* count, which is the length of the overall transaction. This is useful for
|
||||
* reading metadata from the flash chip. Do *NOT* use it to mutate the data
|
||||
* stored on the flash because it will not flush the cache.
|
||||
*
|
||||
* \param txbuf Pointer to a byte buffer which will be transmitted to the flash
|
||||
* \param rxbuf Pointer to a byte buffer where data received from the flash will be written
|
||||
* \param count Length in bytes of txbuf and of rxbuf
|
||||
*/
|
||||
void flash_do_cmd(const uint8_t *txbuf, uint8_t *rxbuf, size_t count);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -85,6 +85,14 @@ uint i2c_set_baudrate(i2c_inst_t *i2c, uint baudrate) {
|
|||
i2c->hw->fs_scl_lcnt = lcnt;
|
||||
i2c->hw->fs_spklen = lcnt < 16 ? 1 : lcnt / 16;
|
||||
|
||||
// The SDA hold time should be at least 300 ns, per the I2C standard.
|
||||
// sda_hold_count [cycles] = freq_in [cycles/s]) * 300ns * (1s / 1e9ns)
|
||||
// Reduce 300/1e9 to 3/1e7 to avoid really big numbers.
|
||||
// Add 1 to avoid division truncation.
|
||||
uint sda_hold_count = ((freq_in * 3) / 10000000) + 1;
|
||||
i2c->hw->sda_hold =
|
||||
I2C_IC_SDA_HOLD_IC_SDA_RX_HOLD_RESET << I2C_IC_SDA_HOLD_IC_SDA_RX_HOLD_LSB |
|
||||
sda_hold_count << I2C_IC_SDA_HOLD_IC_SDA_TX_HOLD_LSB;
|
||||
i2c->hw->enable = 1;
|
||||
return freq_in / period;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@
|
|||
#include "hardware/regs/xosc.h"
|
||||
#include "hardware/structs/xosc.h"
|
||||
|
||||
#define XOSC_STARTUP_DELAY_MULTIPLIER (64)
|
||||
|
||||
void xosc_init(void) {
|
||||
// Assumes 1-15 MHz input
|
||||
assert(XOSC_MHZ <= 15);
|
||||
|
|
@ -20,7 +22,8 @@ void xosc_init(void) {
|
|||
|
||||
// Set xosc startup delay
|
||||
uint32_t startup_delay = (((12 * MHZ) / 1000) + 128) / 256;
|
||||
xosc_hw->startup = startup_delay;
|
||||
// Lengthen startup delay to accomodate slow-starting oscillators
|
||||
xosc_hw->startup = startup_delay * XOSC_STARTUP_DELAY_MULTIPLIER;
|
||||
|
||||
// Set the enable bit now that we have set freq range and startup delay
|
||||
hw_set_bits(&xosc_hw->ctrl, XOSC_CTRL_ENABLE_VALUE_ENABLE << XOSC_CTRL_ENABLE_LSB);
|
||||
|
|
@ -43,4 +46,4 @@ void xosc_dormant(void) {
|
|||
xosc_hw->dormant = XOSC_DORMANT_VALUE_DORMANT;
|
||||
// Wait for it to become stable once woken up
|
||||
while(!(xosc_hw->status & XOSC_STATUS_STABLE_BITS));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue