mtb_serial_memory.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899
  1. /***********************************************************************************************//**
  2. * \file mtb_serial_memory.c
  3. *
  4. * \brief
  5. * Provides APIs for interacting with an external memory connected to the SPI or
  6. * serial memory interface, uses SFDP to auto-discover memory properties if SFDP is
  7. * enabled in the configuration.
  8. *
  9. ***************************************************************************************************
  10. * \copyright
  11. * Copyright 2018-2024 Cypress Semiconductor Corporation (an Infineon company) or
  12. * an affiliate of Cypress Semiconductor Corporation
  13. *
  14. * SPDX-License-Identifier: Apache-2.0
  15. *
  16. * Licensed under the Apache License, Version 2.0 (the "License");
  17. * you may not use this file except in compliance with the License.
  18. * You may obtain a copy of the License at
  19. *
  20. * http://www.apache.org/licenses/LICENSE-2.0
  21. *
  22. * Unless required by applicable law or agreed to in writing, software
  23. * distributed under the License is distributed on an "AS IS" BASIS,
  24. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  25. * See the License for the specific language governing permissions and
  26. * limitations under the License.
  27. **************************************************************************************************/
  28. #include <stdbool.h>
  29. #include "mtb_serial_memory.h"
  30. #include "cy_utils.h"
  31. #ifdef CY_IP_MXSMIF
  32. #if defined(__cplusplus)
  33. extern "C" {
  34. #endif
  35. /** \cond INTERNAL */
  36. /** Timeout to apply while polling the memory for its ready status after quad
  37. * enable command has been sent out. Quad enable is a non-volatile write.
  38. */
  39. #define MTB_SERIAL_MEMORY_QUAD_ENABLE_TIMEOUT_US (5000lu) // in microseconds
  40. /** Number of loops to run while polling the SMIF for its busy status. */
  41. #define _MTB_SERIAL_MEMORY_SMIF_BUSY_CHECK_LOOP_COUNT (10lu)
  42. /** Timeout to apply per loop while polling the SMIF for its busy status. */
  43. #define _MTB_SERIAL_MEMORY_SMIF_BUSY_CHECK_TIMEOUT_MS (1lu) // in milliseconds
  44. /* Maximum number of bytes that can be read by SMIF in one transfer */
  45. #define _MTB_SERIAL_MEMORY_SMIF_MAX_RX_COUNT (65536lu)
  46. #define _MTB_SERIAL_MEMORY_MSB_SHIFT_EIGHT (0x08u)
  47. #define _MTB_SERIAL_MEMORY_LSB_MASK (0xFFlu)
  48. /* Masks used for checking the flag bits */
  49. #define _MTB_SERIAL_MEMORY_FLAG_SETUP_DONE (0x01lu << 0)
  50. #define _MTB_SERIAL_MEMORY_FLAG_ASYNC_INIT_DONE (0x01lu << 1)
  51. #define _MTB_SERIAL_MEMORY_FLAG_READ_IN_PROGRESS (0x01lu << 2)
  52. #define _MTB_SERIAL_MEMORY_IS_EVEN(value) \
  53. ((value % 2 == 0) ? true : false)
  54. /* Maximum frequency that SFDP can operate at. It's differenet depending on the memory module
  55. * but the SFDP protocol requires that all memories reach at least 50MHz */
  56. #define _MTB_SERIAL_MEMORY_MAX_SFDP_FREQ (50000000u)
  57. /* Some devices execute program code from external memory (XIP mode).
  58. * SerialFlash still can work on such devices, but with some limitations. */
  59. #if defined(CY_DEVICE_CYW20829)
  60. #define _MTB_SERIAL_MEMORY_USING_XIP_MEMORY
  61. #endif /* defined(CY_DEVICE_CYW20829) */
  62. /*******************************************************************************
  63. * Private Function Definitions
  64. *******************************************************************************/
  65. //------------------------------------------------------------------------------
  66. // _mtb_serial_memory_slaveslot_to_memnum
  67. //------------------------------------------------------------------------------
  68. static uint8_t _mtb_serial_memory_slaveslot_to_memnum(uint32_t slaveslot)
  69. {
  70. uint8_t memnum;
  71. switch (slaveslot)
  72. {
  73. case MTB_SERIAL_MEMORY_CHIP_SELECT_0:
  74. {
  75. memnum = 0U;
  76. break;
  77. }
  78. case MTB_SERIAL_MEMORY_CHIP_SELECT_1:
  79. {
  80. memnum = 1U;
  81. break;
  82. }
  83. case MTB_SERIAL_MEMORY_CHIP_SELECT_2:
  84. {
  85. memnum = 2U;
  86. break;
  87. }
  88. case MTB_SERIAL_MEMORY_CHIP_SELECT_3:
  89. {
  90. memnum = 3U;
  91. break;
  92. }
  93. default:
  94. {
  95. memnum = 0xFFU;
  96. break;
  97. }
  98. } /* End Switch */
  99. return memnum;
  100. }
  101. //------------------------------------------------------------------------------
  102. // _mtb_serial_memory_is_flag_set
  103. //------------------------------------------------------------------------------
  104. bool _mtb_serial_memory_is_flag_set(mtb_serial_memory_t* obj, uint32_t mask)
  105. {
  106. return ((obj->status_flags & mask) != 0U);
  107. }
  108. //------------------------------------------------------------------------------
  109. // _mtb_serial_memory_clear_flag
  110. //------------------------------------------------------------------------------
  111. void _mtb_serial_memory_clear_flag(mtb_serial_memory_t* obj, uint32_t mask)
  112. {
  113. obj->status_flags &= ~mask;
  114. }
  115. //--------------------------------------------------------------------------------------------------
  116. // _mtb_serial_memory_set_flag
  117. //--------------------------------------------------------------------------------------------------
  118. void _mtb_serial_memory_set_flag(mtb_serial_memory_t* obj, uint32_t mask)
  119. {
  120. obj->status_flags |= mask;
  121. }
  122. //--------------------------------------------------------------------------------------------------
  123. // _mtb_serial_memory_is_busy
  124. //--------------------------------------------------------------------------------------------------
  125. bool _mtb_serial_memory_is_busy(mtb_serial_memory_t* obj)
  126. {
  127. CY_ASSERT(obj != NULL);
  128. CY_ASSERT(obj->base != NULL);
  129. uint32_t smif_status = Cy_SMIF_GetTransferStatus(obj->base, &obj->mem_context->smif_context);
  130. return (Cy_SMIF_BusyCheck(obj->base) ||
  131. ((CY_SMIF_SEND_BUSY == smif_status) || (CY_SMIF_RX_BUSY == smif_status)));
  132. }
  133. //--------------------------------------------------------------------------------------------------
  134. // _mtb_serial_memory_mutex_acquire
  135. //--------------------------------------------------------------------------------------------------
  136. static inline cy_rslt_t _mtb_serial_memory_mutex_acquire(mtb_serial_memory_t* obj)
  137. {
  138. #if defined(MTB_SERIAL_MEMORY_THREAD_SAFE)
  139. return cy_rtos_get_mutex(&obj->mutex, CY_RTOS_NEVER_TIMEOUT);
  140. #else /* defined(MTB_SERIAL_MEMORY_THREAD_SAFE) */
  141. CY_UNUSED_PARAMETER(obj);
  142. return CY_RSLT_SUCCESS;
  143. #endif /* defined(MTB_SERIAL_MEMORY_THREAD_SAFE) */
  144. }
  145. //--------------------------------------------------------------------------------------------------
  146. // _mtb_serial_memory_mutex_release
  147. //--------------------------------------------------------------------------------------------------
  148. static inline cy_rslt_t _mtb_serial_memory_mutex_release(mtb_serial_memory_t* obj)
  149. {
  150. #if defined(MTB_SERIAL_MEMORY_THREAD_SAFE)
  151. return cy_rtos_set_mutex(&obj->mutex);
  152. #else /* defined(MTB_SERIAL_MEMORY_THREAD_SAFE) */
  153. CY_UNUSED_PARAMETER(obj);
  154. return CY_RSLT_SUCCESS;
  155. #endif /* defined(MTB_SERIAL_MEMORY_THREAD_SAFE) */
  156. }
  157. //--------------------------------------------------------------------------------------------------
  158. // _mtb_serial_memory_compute_data_rate
  159. //--------------------------------------------------------------------------------------------------
  160. cy_en_smif_data_rate_t _mtb_serial_memory_compute_data_rate(mtb_serial_memory_t* obj)
  161. {
  162. cy_en_smif_data_rate_t dataRate;
  163. cy_stc_smif_mem_config_t const* memCfg =
  164. obj->mem_context->block_config->memConfig[obj->smif_active_slot];
  165. if ((memCfg->deviceCfg != NULL) &&
  166. (obj->mem_context->block_config->memConfig[obj->smif_active_slot]->deviceCfg->readCmd->
  167. dataRate == CY_SMIF_DDR) &&
  168. (obj->mem_context->block_config->memConfig[obj->smif_active_slot]->deviceCfg->programCmd->
  169. dataRate == CY_SMIF_DDR))
  170. {
  171. dataRate = CY_SMIF_DDR;
  172. }
  173. else
  174. {
  175. dataRate = CY_SMIF_SDR;
  176. }
  177. return dataRate;
  178. }
  179. #if (CY_IP_MXSMIF_VERSION >= 4)
  180. // --------------------------------------------------------------------------------------------------
  181. // _mtb_serial_memory_set_rx_capture_mode
  182. // --------------------------------------------------------------------------------------------------
  183. cy_rslt_t _mtb_serial_memory_set_rx_capture_mode(mtb_serial_memory_t* obj,
  184. cy_en_smif_capture_mode_t rx_capture_mode)
  185. {
  186. cy_en_smif_status_t smif_status = CY_SMIF_SUCCESS;
  187. cy_rslt_t result = CY_RSLT_SUCCESS;
  188. /* We need to disable before we can successfully update Capture mode */
  189. Cy_SMIF_Disable(obj->base);
  190. /* Set capture mode */
  191. smif_status = Cy_SMIF_SetRxCaptureMode(obj->base, rx_capture_mode,
  192. (cy_en_smif_slave_select_t)obj->chip_select);
  193. if (smif_status != CY_SMIF_SUCCESS)
  194. {
  195. result = MTB_RSLT_SERIAL_MEMORY_ERR_RX_CAPTURE;
  196. }
  197. Cy_SMIF_Enable(obj->base, &obj->mem_context->smif_context);
  198. return result;
  199. }
  200. // --------------------------------------------------------------------------------------------------
  201. // _mtb_serial_memory_enable_octal_mode_if_needed
  202. // --------------------------------------------------------------------------------------------------
  203. // This is needed in the case of an external memory that by default is set up as SPI and then needs
  204. // to be set to Octal mode via the specified command. For memories that by default are set up as
  205. // OSPI such a command does not exist.
  206. static cy_rslt_t _mtb_serial_memory_enable_octal_mode_if_needed(mtb_serial_memory_t* obj)
  207. {
  208. cy_en_smif_status_t smif_status = CY_SMIF_SUCCESS;
  209. cy_rslt_t result = CY_RSLT_SUCCESS;
  210. cy_stc_smif_mem_config_t const* memCfg =
  211. obj->mem_context->block_config->memConfig[obj->smif_active_slot];
  212. if ((memCfg->deviceCfg != NULL) &&
  213. (obj->mem_context->block_config->memConfig[obj->smif_active_slot]->deviceCfg->
  214. writeStsRegOeCmd !=
  215. NULL))
  216. {
  217. if ((obj->mem_context->block_config->memConfig[obj->smif_active_slot]->deviceCfg->readCmd->
  218. dataWidth
  219. == CY_SMIF_WIDTH_OCTAL) ||
  220. (obj->mem_context->block_config->memConfig[obj->smif_active_slot]->deviceCfg->programCmd
  221. ->
  222. dataWidth == CY_SMIF_WIDTH_OCTAL))
  223. {
  224. cy_en_smif_data_rate_t dataRate = _mtb_serial_memory_compute_data_rate(obj);
  225. smif_status = Cy_SMIF_MemOctalEnable(obj->base,
  226. obj->mem_context->block_config->memConfig[obj->
  227. smif_active_slot],
  228. dataRate,
  229. &obj->mem_context->smif_context);
  230. if (CY_SMIF_SUCCESS == smif_status)
  231. {
  232. result = _mtb_serial_memory_set_rx_capture_mode(obj,
  233. (dataRate ==
  234. CY_SMIF_DDR) ? CY_SMIF_SEL_XSPI_HYPERBUS_WITH_DQS : CY_SMIF_SEL_NORMAL_SPI);
  235. }
  236. else
  237. {
  238. result = MTB_RSLT_SERIAL_MEMORY_ERR_OCTAL_ENABLE;
  239. }
  240. }
  241. }
  242. return result;
  243. }
  244. //--------------------------------------------------------------------------------------------------
  245. // _mtb_serial_memory_set_capture_mode_if_needed
  246. //--------------------------------------------------------------------------------------------------
  247. static cy_rslt_t _mtb_serial_memory_set_capture_mode_if_needed(mtb_serial_memory_t* obj)
  248. {
  249. cy_rslt_t status = CY_SMIF_SUCCESS;
  250. cy_stc_smif_mem_config_t const* memCfg =
  251. obj->mem_context->block_config->memConfig[obj->smif_active_slot];
  252. if (0 != (obj->mem_context->block_config->memConfig[obj->smif_active_slot]->flags &
  253. CY_SMIF_FLAG_DETECT_SFDP))
  254. {
  255. // If we want to perform SFDP we need the SMIF to be configured in NORMAL SPI MODE as the
  256. // protocol is working in single SPI mode. Therefore if a previous setting had put the
  257. // memory in XSPI mode we need to revert it so that we can perform SFDP correctly.
  258. if ((obj->base->CTL2 & SMIF_CORE_CTL2_RX_CAPTURE_MODE_Msk) >>
  259. SMIF_CORE_CTL2_RX_CAPTURE_MODE_Pos ==
  260. CY_SMIF_SEL_XSPI_HYPERBUS_WITH_DQS)
  261. {
  262. status = _mtb_serial_memory_set_rx_capture_mode(obj, CY_SMIF_SEL_NORMAL_SPI);
  263. }
  264. }
  265. else
  266. {
  267. if (memCfg->deviceCfg != NULL)
  268. {
  269. // If we are not performing SFDP but we are connecting to an OSPI memory we need to
  270. // check
  271. // the data rate and set it to HYPERBUS for DDR mode.
  272. if ((obj->mem_context->block_config->memConfig[obj->smif_active_slot]->deviceCfg->
  273. readCmd->
  274. dataWidth
  275. == CY_SMIF_WIDTH_OCTAL) ||
  276. (obj->mem_context->block_config->memConfig[obj->smif_active_slot]->deviceCfg->
  277. programCmd->
  278. dataWidth == CY_SMIF_WIDTH_OCTAL))
  279. {
  280. cy_en_smif_data_rate_t dataRate = _mtb_serial_memory_compute_data_rate(obj);
  281. status = _mtb_serial_memory_set_rx_capture_mode(obj, (dataRate == CY_SMIF_DDR) ?
  282. CY_SMIF_SEL_XSPI_HYPERBUS_WITH_DQS : CY_SMIF_SEL_NORMAL_SPI);
  283. }
  284. }
  285. }
  286. return status;
  287. }
  288. #endif /* (CY_IP_MXSMIF_VERSION >= 4) */
  289. /** \endcond */
  290. //--------------------------------------------------------------------------------------------------
  291. // mtb_serial_memory_setup
  292. //--------------------------------------------------------------------------------------------------
  293. cy_rslt_t mtb_serial_memory_setup(
  294. mtb_serial_memory_t* obj,
  295. mtb_serial_memory_chip_select_t smif_active_chip,
  296. SMIF_Type* base,
  297. const mtb_hal_clock_t* clock,
  298. cy_stc_smif_mem_context_t* mem_context,
  299. cy_stc_smif_mem_info_t* mem_info,
  300. const cy_stc_smif_block_config_t* block_config)
  301. {
  302. cy_rslt_t result = CY_RSLT_SUCCESS;
  303. cy_stc_smif_mem_config_t const* memCfg;
  304. uint8_t memnum;
  305. CY_ASSERT(NULL != obj);
  306. CY_ASSERT(NULL != base);
  307. CY_ASSERT(NULL != clock);
  308. CY_ASSERT(NULL != mem_context);
  309. CY_ASSERT(NULL != mem_info);
  310. CY_ASSERT(NULL != block_config);
  311. mem_context->block_config = block_config;
  312. obj->chip_select = smif_active_chip;
  313. obj->base = base;
  314. obj->clock = clock;
  315. obj->mem_context = mem_context;
  316. obj->mem_info = mem_info;
  317. memnum = _mtb_serial_memory_slaveslot_to_memnum(obj->chip_select);
  318. for (uint32_t i = 0; i < block_config->memCount; i++)
  319. {
  320. if (block_config->memConfig[i]->slaveSelect ==
  321. (cy_en_smif_slave_select_t)smif_active_chip)
  322. {
  323. obj->smif_active_slot = i;
  324. }
  325. obj->configured_csel |= block_config->memConfig[i]->slaveSelect;
  326. }
  327. memCfg = block_config->memConfig[obj->smif_active_slot];
  328. for (uint32_t idx = 0; idx < block_config->memCount; idx++)
  329. {
  330. Cy_SMIF_SetDataSelect(obj->base, block_config->memConfig[idx]->slaveSelect,
  331. block_config->memConfig[idx]->dataSelect);
  332. }
  333. uint32_t current_freq = (mtb_hal_clock_get_hf_clock_freq(obj->clock->clock_ref)) / 1000000U;
  334. #if (CY_IP_MXSMIF_VERSION >= 2)
  335. //Internal divider of value 2 always present for MXSMIF v2 onwards
  336. current_freq /= 2;
  337. #endif /* (CY_IP_MXSMIF_VERSION >= 2) or other */
  338. /* Iterate through the memory configurations and check if SFDP detection flag is set */
  339. for (uint32_t i = 0; i < block_config->memCount; i++)
  340. {
  341. if (0 != (block_config->memConfig[i]->flags & CY_SMIF_FLAG_DETECT_SFDP))
  342. {
  343. if (current_freq > _MTB_SERIAL_MEMORY_MAX_SFDP_FREQ)
  344. {
  345. result = MTB_RSLT_SERIAL_MEMORY_ERR_UNSUPPORTED;
  346. break;
  347. }
  348. }
  349. }
  350. if (CY_RSLT_SUCCESS == result)
  351. {
  352. #if (CY_IP_MXSMIF_VERSION >= 4)
  353. // For MemInit to complete successfully the SMIF peripheral needs to have
  354. // capture mode set to normal.
  355. // SFDP mode cannot be used for octal memories that have already been initialized
  356. // and gone through the octal enable process.
  357. result = _mtb_serial_memory_set_capture_mode_if_needed(obj);
  358. if (CY_SMIF_SUCCESS == result)
  359. #endif // if (CY_IP_MXSMIF_VERSION >= 5)
  360. {
  361. cy_en_smif_status_t smif_status = CY_SMIF_SUCCESS;
  362. result = CY_RSLT_SUCCESS;
  363. // Perform SFDP detection and XIP register configuration depending on the memory
  364. // configuration.
  365. smif_status = Cy_SMIF_MemNumInit(obj->base, block_config, mem_context);
  366. if (CY_SMIF_SUCCESS == smif_status)
  367. {
  368. smif_status =
  369. Cy_SMIF_MemNumGetInfo(mem_context, memnum, mem_info);
  370. }
  371. if (CY_SMIF_SUCCESS == smif_status)
  372. {
  373. if (memCfg->deviceCfg != NULL)
  374. {
  375. // Enable Quad mode (1-1-4 or 1-4-4 modes) to use all the four I/Os during
  376. // communication if needed.
  377. if ((block_config->memConfig[obj->smif_active_slot]->deviceCfg->
  378. readCmd->
  379. dataWidth == CY_SMIF_WIDTH_QUAD) ||
  380. (block_config->memConfig[obj->smif_active_slot]->deviceCfg->
  381. programCmd
  382. ->dataWidth == CY_SMIF_WIDTH_QUAD))
  383. {
  384. bool isQuadEnabled = false;
  385. smif_status =
  386. Cy_SMIF_MemIsQuadEnabled(obj->base,
  387. block_config->memConfig[obj->
  388. smif_active_slot],
  389. &isQuadEnabled,
  390. &obj->mem_context->smif_context);
  391. if ((CY_SMIF_SUCCESS == smif_status) && !isQuadEnabled)
  392. {
  393. smif_status =
  394. Cy_SMIF_MemEnableQuadMode(obj->base,
  395. block_config->memConfig[obj->
  396. smif_active_slot],
  397. MTB_SERIAL_MEMORY_QUAD_ENABLE_TIMEOUT_US,
  398. &obj->mem_context->smif_context);
  399. }
  400. }
  401. }
  402. }
  403. if (CY_SMIF_SUCCESS != smif_status)
  404. {
  405. result = (cy_rslt_t)smif_status;
  406. }
  407. }
  408. }
  409. #if (CY_IP_MXSMIF_VERSION >= 4)
  410. // Enable Octal mode (8S-8S-8S or 8D-8D-8D modes) to use all the eight I/Os during
  411. // communication if needed.
  412. if (CY_RSLT_SUCCESS == result)
  413. {
  414. result = _mtb_serial_memory_enable_octal_mode_if_needed(obj);
  415. }
  416. #endif // if (CY_IP_MXSMIF_VERSION >= 4)
  417. #if defined(MTB_SERIAL_MEMORY_THREAD_SAFE)
  418. if (CY_RSLT_SUCCESS == result)
  419. {
  420. /* Initialize the mutex */
  421. result = cy_rtos_init_mutex(&obj->mutex);
  422. }
  423. #endif /* #if defined(MTB_SERIAL_MEMORY_THREAD_SAFE) */
  424. if (CY_RSLT_SUCCESS == result)
  425. {
  426. _mtb_serial_memory_set_flag(obj, _MTB_SERIAL_MEMORY_FLAG_SETUP_DONE);
  427. }
  428. return result;
  429. }
  430. #if !defined(COMPONENT_SECURE_DEVICE)
  431. //--------------------------------------------------------------------------------------------------
  432. // mtb_serial_memory_setup_nonsecure
  433. //--------------------------------------------------------------------------------------------------
  434. cy_rslt_t mtb_serial_memory_setup_nonsecure(
  435. mtb_serial_memory_t* obj,
  436. mtb_serial_memory_chip_select_t smif_active_chip,
  437. SMIF_Type* base,
  438. cy_stc_smif_mem_context_t* mem_context,
  439. cy_stc_smif_mem_info_t* mem_info)
  440. {
  441. cy_rslt_t result = CY_RSLT_SUCCESS;
  442. uint8_t memnum;
  443. CY_ASSERT(NULL != obj);
  444. CY_ASSERT(NULL != base);
  445. CY_ASSERT(NULL != mem_context);
  446. CY_ASSERT(NULL != mem_info);
  447. obj->chip_select = smif_active_chip;
  448. obj->base = base;
  449. obj->mem_context = mem_context;
  450. obj->mem_info = mem_info;
  451. memnum = _mtb_serial_memory_slaveslot_to_memnum(obj->chip_select);
  452. cy_en_smif_status_t smif_status = CY_SMIF_SUCCESS;
  453. result = CY_RSLT_SUCCESS;
  454. smif_status = Cy_SMIF_MemNumSetupNonSecure(base, mem_context);
  455. if (CY_SMIF_SUCCESS == smif_status)
  456. {
  457. smif_status = Cy_SMIF_MemNumGetInfo(mem_context, memnum, mem_info);
  458. }
  459. if (CY_SMIF_SUCCESS != smif_status)
  460. {
  461. result = (cy_rslt_t)smif_status;
  462. }
  463. #if defined(MTB_SERIAL_MEMORY_THREAD_SAFE)
  464. if (CY_RSLT_SUCCESS == result)
  465. {
  466. /* Initialize the mutex */
  467. result = cy_rtos_init_mutex(&obj->mutex);
  468. }
  469. #endif /* #if defined(MTB_SERIAL_MEMORY_THREAD_SAFE) */
  470. if (CY_RSLT_SUCCESS == result)
  471. {
  472. _mtb_serial_memory_set_flag(obj, _MTB_SERIAL_MEMORY_FLAG_SETUP_DONE);
  473. }
  474. return result;
  475. }
  476. #endif // if !defined(COMPONENT_SECURE_DEVICE)
  477. //--------------------------------------------------------------------------------------------------
  478. // mtb_serial_memory_get_size
  479. //--------------------------------------------------------------------------------------------------
  480. size_t mtb_serial_memory_get_size(mtb_serial_memory_t* obj)
  481. {
  482. CY_ASSERT(NULL != obj);
  483. CY_ASSERT(_mtb_serial_memory_is_flag_set(obj, _MTB_SERIAL_MEMORY_FLAG_SETUP_DONE));
  484. return (size_t)obj->mem_info->memSize;
  485. }
  486. //--------------------------------------------------------------------------------------------------
  487. // mtb_serial_memory_get_erase_size
  488. //--------------------------------------------------------------------------------------------------
  489. size_t mtb_serial_memory_get_erase_size(mtb_serial_memory_t* obj, uint32_t addr)
  490. {
  491. CY_ASSERT(NULL != obj);
  492. CY_ASSERT(_mtb_serial_memory_is_flag_set(obj, _MTB_SERIAL_MEMORY_FLAG_SETUP_DONE));
  493. size_t erase_sector_size = obj->mem_info->eraseSize;
  494. uint32_t idx;
  495. uint32_t regionStartAddr;
  496. uint32_t regionEndAddr;
  497. for (idx = 0UL; idx < obj->mem_info->hybridRegionCount; idx++)
  498. {
  499. regionStartAddr = obj->mem_info->hybridRegionInfo[idx].regionStartAddress;
  500. regionEndAddr = obj->mem_info->hybridRegionInfo[idx].regionEndAddress;
  501. if ((addr >= regionStartAddr) && (addr < regionEndAddr))
  502. {
  503. erase_sector_size = obj->mem_info->hybridRegionInfo[idx].eraseSize;
  504. break;
  505. }
  506. }
  507. return erase_sector_size;
  508. }
  509. //--------------------------------------------------------------------------------------------------
  510. // mtb_serial_memory_get_prog_size
  511. //--------------------------------------------------------------------------------------------------
  512. size_t mtb_serial_memory_get_prog_size(mtb_serial_memory_t* obj, uint32_t addr)
  513. {
  514. CY_ASSERT(NULL != obj);
  515. CY_ASSERT(_mtb_serial_memory_is_flag_set(obj, _MTB_SERIAL_MEMORY_FLAG_SETUP_DONE));
  516. CY_UNUSED_PARAMETER(addr);
  517. return (size_t)obj->mem_info->programSize;
  518. }
  519. //--------------------------------------------------------------------------------------------------
  520. // mtb_serial_memory_read
  521. //--------------------------------------------------------------------------------------------------
  522. cy_rslt_t mtb_serial_memory_read(mtb_serial_memory_t* obj, uint32_t addr, size_t length,
  523. uint8_t* buf)
  524. {
  525. CY_ASSERT(NULL != obj);
  526. CY_ASSERT(_mtb_serial_memory_is_flag_set(obj, _MTB_SERIAL_MEMORY_FLAG_SETUP_DONE));
  527. cy_rslt_t result_mutex_rel = CY_RSLT_SUCCESS;
  528. uint8_t memnum = _mtb_serial_memory_slaveslot_to_memnum(obj->chip_select);
  529. cy_rslt_t result = _mtb_serial_memory_mutex_acquire(obj);
  530. if (CY_RSLT_SUCCESS == result)
  531. {
  532. if ((obj->mem_info->flags & CY_SMIF_FLAG_SPI_DEVICE) != 0UL)
  533. {
  534. #if defined(_MTB_SERIAL_MEMORY_EMULATE_BYTE_ADDRESSABLE)
  535. if (_MTB_SERIAL_MEMORY_IS_EVEN(addr))
  536. #endif /* if defined(_MTB_SERIAL_MEMORY_EMULATE_BYTE_ADDRESSABLE) */
  537. {
  538. // Cy_SMIF_MemNumRead() returns error if (addr + length) > total memory size.
  539. result = (cy_rslt_t)Cy_SMIF_MemNumRead(obj->mem_context, memnum, addr, buf, length);
  540. }
  541. #if defined(_MTB_SERIAL_MEMORY_EMULATE_BYTE_ADDRESSABLE)
  542. else if ((!_MTB_SERIAL_MEMORY_IS_EVEN(addr)) && (length == 1))
  543. {
  544. uint32_t temp_addr = addr - 1;
  545. uint8_t temp_buf[2];
  546. memset(temp_buf, 0, length+1);
  547. // Cy_SMIF_MemNumRead() returns error if (addr + length) > total memory size.
  548. result = (cy_rslt_t)Cy_SMIF_MemNumRead(obj->mem_context, memnum, addr, buf,
  549. length + 1);
  550. memcpy(buf, &temp_buf[1], length);
  551. }
  552. else
  553. {
  554. result = MTB_RSLT_SERIAL_MEMORY_ERR_UNSUPPORTED;
  555. }
  556. #endif /* if defined(_MTB_SERIAL_MEMORY_EMULATE_BYTE_ADDRESSABLE) */
  557. }
  558. else if ((obj->mem_info->flags & CY_SMIF_FLAG_HYPERBUS_DEVICE) != 0UL)
  559. {
  560. result = (cy_rslt_t)Cy_SMIF_MemNumHyperBusRead(obj->mem_context, memnum, addr, buf,
  561. length);
  562. }
  563. else
  564. {
  565. result = MTB_RSLT_SERIAL_MEMORY_ERR_UNSUPPORTED;
  566. }
  567. }
  568. result_mutex_rel = _mtb_serial_memory_mutex_release(obj);
  569. /* Give priority to the status of SMIF operation when both SMIF operation
  570. * and mutex release fail.
  571. */
  572. return ((CY_RSLT_SUCCESS == result) ? result_mutex_rel : result);
  573. }
  574. //--------------------------------------------------------------------------------------------------
  575. // mtb_serial_memory_write
  576. //--------------------------------------------------------------------------------------------------
  577. cy_rslt_t mtb_serial_memory_write(mtb_serial_memory_t* obj, uint32_t addr, size_t length,
  578. const uint8_t* buf)
  579. {
  580. CY_ASSERT(NULL != obj);
  581. CY_ASSERT(_mtb_serial_memory_is_flag_set(obj, _MTB_SERIAL_MEMORY_FLAG_SETUP_DONE));
  582. cy_rslt_t result_mutex_rel = CY_RSLT_SUCCESS;
  583. uint8_t memnum = _mtb_serial_memory_slaveslot_to_memnum(obj->chip_select);
  584. cy_rslt_t result = _mtb_serial_memory_mutex_acquire(obj);
  585. if (CY_RSLT_SUCCESS == result)
  586. {
  587. if ((obj->mem_info->flags & CY_SMIF_FLAG_SPI_DEVICE) != 0UL)
  588. {
  589. #if defined(_MTB_SERIAL_MEMORY_EMULATE_BYTE_ADDRESSABLE)
  590. if (_MTB_SERIAL_MEMORY_IS_EVEN(addr) && _MTB_SERIAL_MEMORY_IS_EVEN(length))
  591. #endif /* if defined(_MTB_SERIAL_MEMORY_EMULATE_BYTE_ADDRESSABLE) */
  592. {
  593. // Cy_SMIF_MemNumWrite() returns error if (addr + length) > total memory size.
  594. result =
  595. (cy_rslt_t)Cy_SMIF_MemNumWrite(obj->mem_context, memnum, addr, buf, length);
  596. }
  597. #if defined(_MTB_SERIAL_MEMORY_EMULATE_BYTE_ADDRESSABLE)
  598. else if (length == 1)
  599. {
  600. uint32_t full_addr = addr;
  601. if (!_MTB_SERIAL_MEMORY_IS_EVEN(addr))
  602. {
  603. full_addr -= 1;
  604. }
  605. uint8_t full_buf[2];
  606. memset(full_buf, 0, sizeof(full_buf));
  607. size_t full_length = 2;
  608. result = mtb_serial_memory_read(obj, full_addr, full_length, full_buf);
  609. if (CY_RSLT_SUCCESS == result)
  610. {
  611. if (_MTB_SERIAL_MEMORY_IS_EVEN(addr))
  612. {
  613. memcpy(&full_buf[0], buf, length);
  614. }
  615. else
  616. {
  617. memcpy(&full_buf[1], buf, length);
  618. }
  619. result = (cy_rslt_t)Cy_SMIF_MemNumWrite(obj->mem_context, memnum, full_addr,
  620. full_buf, full_length);
  621. }
  622. }
  623. else
  624. {
  625. result = MTB_RSLT_SERIAL_MEMORY_ERR_UNSUPPORTED;
  626. }
  627. #endif /* if defined(_MTB_SERIAL_MEMORY_EMULATE_BYTE_ADDRESSABLE) */
  628. }
  629. else if ((obj->mem_info->flags & CY_SMIF_FLAG_HYPERBUS_DEVICE) != 0UL)
  630. {
  631. result = (cy_rslt_t)Cy_SMIF_MemNumHyperBusWrite(obj->mem_context, memnum, addr, buf,
  632. length);
  633. }
  634. else
  635. {
  636. result = MTB_RSLT_SERIAL_MEMORY_ERR_UNSUPPORTED;
  637. }
  638. }
  639. result_mutex_rel = _mtb_serial_memory_mutex_release(obj);
  640. /* Give priority to the status of SMIF operation when both SMIF operation
  641. * and mutex release fail.
  642. */
  643. return ((CY_RSLT_SUCCESS == result) ? result_mutex_rel : result);
  644. }
  645. //--------------------------------------------------------------------------------------------------
  646. // mtb_serial_memory_erase
  647. //--------------------------------------------------------------------------------------------------
  648. cy_rslt_t mtb_serial_memory_erase(mtb_serial_memory_t* obj, uint32_t addr, size_t length)
  649. {
  650. CY_ASSERT(NULL != obj);
  651. CY_ASSERT(_mtb_serial_memory_is_flag_set(obj, _MTB_SERIAL_MEMORY_FLAG_SETUP_DONE));
  652. cy_rslt_t result_mutex_rel = CY_RSLT_SUCCESS;
  653. uint8_t memnum = _mtb_serial_memory_slaveslot_to_memnum(obj->chip_select);
  654. cy_rslt_t result = _mtb_serial_memory_mutex_acquire(obj);
  655. if (CY_RSLT_SUCCESS == result)
  656. {
  657. if ((obj->mem_info->flags & CY_SMIF_FLAG_SPI_DEVICE) != 0UL)
  658. {
  659. // If the erase is for the entire chip, use chip erase command
  660. if ((addr == 0u) && (length == mtb_serial_memory_get_size(obj)))
  661. {
  662. result = (cy_rslt_t)Cy_SMIF_MemNumEraseChip(obj->mem_context, memnum);
  663. }
  664. else
  665. {
  666. // Cy_SMIF_MemEraseSector() returns error if (addr + length) > total memory size or
  667. // if
  668. // addr is not aligned to erase sector size or if (addr + length) is not aligned to
  669. // erase sector size.
  670. result =
  671. (cy_rslt_t)Cy_SMIF_MemNumEraseSector(obj->mem_context, memnum, addr, length);
  672. }
  673. }
  674. else
  675. {
  676. result = MTB_RSLT_SERIAL_MEMORY_ERR_UNSUPPORTED;
  677. }
  678. }
  679. result_mutex_rel = _mtb_serial_memory_mutex_release(obj);
  680. /* Give priority to the status of SMIF operation when both SMIF operation
  681. * and mutex release fail.
  682. */
  683. return ((CY_RSLT_SUCCESS == result) ? result_mutex_rel : result);
  684. }
  685. //--------------------------------------------------------------------------------------------------
  686. // mtb_serial_memory_enable_xip
  687. //--------------------------------------------------------------------------------------------------
  688. cy_rslt_t mtb_serial_memory_enable_xip(mtb_serial_memory_t* obj, bool enable)
  689. {
  690. CY_ASSERT(NULL != obj);
  691. CY_ASSERT(_mtb_serial_memory_is_flag_set(obj, _MTB_SERIAL_MEMORY_FLAG_SETUP_DONE));
  692. if (enable)
  693. {
  694. Cy_SMIF_SetMode(obj->base, CY_SMIF_MEMORY);
  695. }
  696. else
  697. {
  698. Cy_SMIF_SetMode(obj->base, CY_SMIF_NORMAL);
  699. }
  700. return CY_RSLT_SUCCESS;
  701. }
  702. //--------------------------------------------------------------------------------------------------
  703. // mtb_serial_memory_set_active_chip
  704. //--------------------------------------------------------------------------------------------------
  705. cy_rslt_t mtb_serial_memory_set_active_chip(mtb_serial_memory_t* obj,
  706. mtb_serial_memory_chip_select_t chip_select)
  707. {
  708. CY_ASSERT(NULL != obj);
  709. CY_ASSERT(_mtb_serial_memory_is_flag_set(obj, _MTB_SERIAL_MEMORY_FLAG_SETUP_DONE));
  710. cy_rslt_t result = CY_RSLT_SUCCESS;
  711. if ((obj->configured_csel & chip_select) > 0)
  712. {
  713. for (uint32_t i = 0; i < obj->mem_context->block_config->memCount; i++)
  714. {
  715. if (obj->mem_context->block_config->memConfig[i]->slaveSelect ==
  716. (cy_en_smif_slave_select_t)chip_select)
  717. {
  718. obj->smif_active_slot = i;
  719. obj->chip_select = chip_select;
  720. break;
  721. }
  722. }
  723. }
  724. else
  725. {
  726. result = MTB_RSLT_SERIAL_MEMORY_ERR_BAD_PARAM;
  727. }
  728. return result;
  729. }
  730. //--------------------------------------------------------------------------------------------------
  731. // mtb_serial_memory_get_chip_count
  732. //--------------------------------------------------------------------------------------------------
  733. uint32_t mtb_serial_memory_get_chip_count(mtb_serial_memory_t* obj)
  734. {
  735. CY_ASSERT(NULL != obj);
  736. CY_ASSERT(_mtb_serial_memory_is_flag_set(obj, _MTB_SERIAL_MEMORY_FLAG_SETUP_DONE));
  737. return obj->mem_context->block_config->memCount;
  738. }
  739. //--------------------------------------------------------------------------------------------------
  740. // mtb_serial_memory_get_active_chip
  741. //--------------------------------------------------------------------------------------------------
  742. uint32_t mtb_serial_memory_get_active_chip(mtb_serial_memory_t* obj)
  743. {
  744. CY_ASSERT(NULL != obj);
  745. CY_ASSERT(_mtb_serial_memory_is_flag_set(obj, _MTB_SERIAL_MEMORY_FLAG_SETUP_DONE));
  746. return obj->chip_select;
  747. }
  748. //--------------------------------------------------------------------------------------------------
  749. // mtb_serial_memory_set_write_enable
  750. //--------------------------------------------------------------------------------------------------
  751. cy_rslt_t mtb_serial_memory_set_write_enable(mtb_serial_memory_t* obj, bool enable)
  752. {
  753. CY_ASSERT(NULL != obj);
  754. CY_ASSERT(_mtb_serial_memory_is_flag_set(obj, _MTB_SERIAL_MEMORY_FLAG_SETUP_DONE));
  755. if (enable)
  756. {
  757. return (cy_rslt_t)Cy_SMIF_MemCmdWriteEnable(obj->base,
  758. obj->mem_context->block_config->memConfig[obj->
  759. smif_active_slot],
  760. &obj->mem_context->smif_context);
  761. }
  762. else
  763. {
  764. return (cy_rslt_t)Cy_SMIF_MemCmdWriteDisable(obj->base,
  765. obj->mem_context->block_config->memConfig[obj->
  766. smif_active_slot],
  767. &obj->mem_context->smif_context);
  768. }
  769. }
  770. #if defined(__cplusplus)
  771. }
  772. #endif
  773. #endif /* CY_IP_MXSMIF */