Other Parts Discussed in Thread: SYSBIOS
Why is the UART open already with the base addr 0x44E09000 even if it is first time to call UART_open?
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hi Anping,
The reason the base address is already set for UART0 is because this is statically defined in the UART LLD library. This is by design, but if for some reason you want to change this value you can do so using the UART_socGetInitCfg() / UART_socSetInitCfg() API functions.
Details are presented below.
Regards,
Frank
This is the base address of the UART0 registers. Please see the AM335x TRM, Table 2-2 (spruh73p.pdf):
Please inspect the UART_open() code in uart\src\UART_drv.c:
/*
* ======== UART_open ========
*/
UART_Handle UART_open(uint32_t index, UART_Params *params)
{
UART_Handle handle;
/* Get handle for this driver instance */
handle = (UART_Handle)&(UART_config[index]);
return (handle->fxnTablePtr->openFxn(handle, params));
}
The UART_config[] table is defined in uart\soc\am335xUART_soc.c. The entry in UART_config[] for UART0 is shown table below:
/* UART configuration structure */
UART_config_list UART_config = {
{
&UART_FxnTable_v1,
&UartObjects[0],
&uartInitCfg[0]
},
This uartInitCfg[] table is also contained in uart\soc\am335xUART_soc.c. The first portion of the 0th entry of this table is shown below:
/* UART configuration structure */
UART_HwAttrs uartInitCfg[CSL_UART_PER_CNT] =
{
{
SOC_UART_0_REGS,
72,
0,
48000000U,
// etc.
},
Searching for the above definition in the UART LLD code:
$ grep -rI -n -i --regexp="SOC_UART_0_REGS" --include "*.h"
starterware/include/hw/soc_am335x.h:58:#define SOC_UART_0_REGS (0x44E09000)
Hi Frank
C:\ti\pdk_am335x_1_0_15\packages\MyExampleProjects\UART_BasicExample_bbbAM335x_armTestProject line 2290 uart = UART_open(uartTestInstance, &uartParams); UART_open return NULL
C:\ti\pdk_am335x_1_0_16\packages\MyExampleProjects\UART_BasicExample_bbbAM335x_armTestProject line 2321 uart = UART_open(uartTestInstance, &uartParams); UART_open doesn't return NULL Here uartTestInstance = 0 or UART0. If it is design, they will all return NULL. I like to know if UART0 is open, where does it open? Where can I find UART handle? I can close it. My project's UART_open return NULL because UART0 is open. Thanks
Hi Frank
grep -rI -n -i --regexp="SOC_UART_0_REGS" --include "*.h"
is a linux command. What is its Window command? Thanks
Anping,
I'm using Git bash on Windows to issue this grep command. You can also install cygwin to provide Linux-style commands on Windows.
Maybe there are other (better?) tools for searching the files in a Windows directory tree for a keyword. I don't have a recommendation.
Regards,
Frank
Hi Anping,
Is this in your own code, or TI OOB example code?
Have you tried stepping into the code to see where the crash occurs?
Can you provide a "toy" example that demonstrates the crash so I can better help you debug?
Thanks,
Frank
Hi Anping,
Did you call UART_init() in your application before calling UART_open()? Please see this comment in the UART_init() API function documentation:
The UART controller needs to be powered up and clocked. The UART_config structure must exist and be persistent before this function can be called. This function must also be called before any other UART driver APIs.
If you have the function call, then likely the UART LLD driver state (and specifically the "isOpen" object member) is being corrupted.
To check "isOpen" in CCS:
This is the code which should be invoked by the UART_init() call:
/*
* ======== UART_init_v1 ========
*/
static void UART_init_v1(UART_Handle handle)
{
/* Mark the object as available */
((UART_V1_Object *)(handle->object))->isOpen = FALSE;
}
Now place a breakpoint on UART_open(), and run to this breakpoint. Is "isOpen" still 0, or has it changed to something else? If it has changed, then of the code between UART_init() and UART_open() is overwriting (corrupting) the UART LLD driver object state.
Regards,
Frank
Anping,
Are you using UART_BasicExample_bbbAM335x_armTestProject Out-of-Box and unmodified? Or have you made modifications to the code? I'm still not clear on that point. Please let me know so I can better assist you.
Thanks,
Frank
Hi Frank
I use UART_BasicExample_bbbAM335x_armTestProject Out-of-Box and unmodified! PDK 15 UART_open return NULL because object "isOpen" is TRUE. PDK 16 UART_open doesn't return NULLbecause object "isOpen" is FALSE. My test project UART_open return NULL because object "isOpen" is TRUE also. My company policy doesn't allow me to share my project. So I like to know what you do to fix "UART_open return NULL" issue in PDK16. I learn a lot from your reply. I can use Git Bash to search file. Thank you for your help. My test project base on your McSPI and UART example projects. I am struggle on "UART_open return NULL" and UART_printf cash using after SPI_transfer with callback function. You can repeat it by yourself by changing SPI_callback function in your McSPI example as what I describe in my another post. Thanks
Hi Anping,
Thanks much for clarifying.
Is there some reason you can't update your project to use AM335x PDK 1.0.16 to resolve the UART_open() return NULL issue?
Regards,
Frank
Anping,
I checked the PRSDK 6.1.0.8 release notes for any fix related to the UART NULL issue you've described, but I didn't find anything.
I also spoke with the UART LLD developer concerning differences between PRSDK 1.0.5 & 1.0.6 which would fix the UART return handle NULL issue. He wasn't aware of any code update which would fix this issue.
I suggest you compare the PDK 1.0.15 & 1.0.16 code (especially for UART LLD code) to see if you can identify any differences which would account for this behavior.
Other than that, I suggest you start using PDK 1.0.16 in your application. The API functions should be identical with those in PDK 1.0.15.
Regards,
Frank
Hi Frank
I use AM335x PDK 1.0.16 on my test project. My test project has UART_open return NULL issue. I can't share my test project. I know AM335x PDK 1.0.15 example project has UART_open return NULL issue also. If you know how to fix AM335x PDK 1.0.15 example project issue. I can solve UART_open return NULL issue too. Thanks
Anping,
Just because you observe the same problem in PDK 1.0.15 example project and (PDK 1.0.16 + your code) doesn't mean the cause of the problem is the same in both cases.
I strongly suggest you follow my suggestions on this post to debug the issue in your application code: https://e2e.ti.com/support/processors/f/791/p/859118/3177785#3177785
Hi Frank
void UART_init(void)
{
if (UART_count == (-((int32_t)1))) {
/* Call each driver's init function */
for (UART_count = 0; UART_config[UART_count].fxnTablePtr != NULL; UART_count++) {
UART_config[UART_count].fxnTablePtr->uartInitFxn((UART_Handle)&(UART_config[UART_count]));
}
}
#if defined (BUILD_MCU)
UART_socInit();
#endif
}
Thanks
https://e2e.ti.com/cfs-file/__key/communityserver-discussions-components-files/791/OSLayerTest.7z
https://e2e.ti.com/cfs-file/__key/communityserver-discussions-components-files/791/1727.OSLayerTest.7z
Hi Frank
I send you zip file which contain project OSLayerTest. its cfg file come from am335x_app_bbbam335x.cfg. I add
var Log = xdc.useModule('xdc.runtime.Log');
var LoggerBuf = xdc.useModule('xdc.runtime.LoggerBuf');
and remove
var SemihostSupport = xdc.useModule('ti.sysbios.rts.gnu.SemiHostSupport');
My OSLayerTest will use UART and SPI. I even comment out
//var Spi = xdc.loadPackage('ti.drv.spi');
//Spi.Settings.socType = socType;
run to UART_init(); IsOpen is 1
Step into UART_init() UART_count = 6 and do nothing.
run to UART_Params_init(&uartParams); step over. It doesn't change uart_cfg's baseAddr (1155567616)
step over UART_Handle uart = UART_open(BOARD_UART_INSTANCE, &uartParams);
uart = NULL because object->isOpen is true (line 741). I appreciate your help. I stun here for a while. I can walk arount UART_printf crash to avoid UART_printf in callback function. Thanks
Anping,
Thanks for sharing the .zip files. I assume the later .zip file is the one I should use?
The contents of the .zip file are intended to demonstrate the UART_open() issue only, correct?
Regards,
Frank
Hi Frank
Yes. My boss give me green light to send it in order for you to solve UART_open() issue. I stun there for a while.Thanks
Hi Frank
I only send one zip file. I don't know why it send twice. I think you can use anyone. Thanks
Hi Anping,
Thanks very much for sharing the example code. I was able to find the cause of the UART_open() issue using this code.
I observe this function call in taskFxn() returns a NULL handle:
UART_Handle uart = UART_open(BOARD_UART_INSTANCE, &uartParams);
The reason this happens is because the UART instance identified by "BOARD_UART_INSTANCE" is already open.
In main(), you call Board_init() with the BOARD_INIT_UART_STDIO parameter set in boardCfg. As a result, this code is executed:
Board_init()
Board_uartStdioInit()
UART_stdioInit(BOARD_UART_INSTANCE);
UART_init();
uart_stdio.uart_handle = UART_open(value, ¶ms);
The source code for UART_stdioInit() is contained in pdk_am335x_1_0_16\packages\ti\drv\uart\src\UART_stdio.c. If you inspect this code, you'll notice the function opens the UART and leaves it open. Essentially this UART instance is dedicated for UART console output.
Thus two things occur in taskFxn():
There are a few things you can do to resolve this problem:
The BOARD UART instance can be found by searching the board library code:
/r/pdk_am335x_1_0_16/packages
grep -rI -n -i --regexp="BOARD_UART_INSTANCE" --include "*.h"
ti/board/src/bbbAM335x/include/board_cfg.h:52:#define BOARD_UART_INSTANCE 0
Regards,
Frank
Anping,
For the third resolution option I provided above, I notice UART_open() aborts when I used UART ID 1. I'm looking into this now.
Hi Frank
Thank you for your explaination. I want to keep BOARD_INIT_UART_STDIO to use UART_printf to trace work flow. I prefer 3) than 2). I think I need to enable UART2, UART3, UART4, UART5 to use UART_open with UART ID 2, 3, 4, 5. Is it right? Thanks
Hi Frank
My BeagleBone Black has UART0 and UART1 enable. Other are disable. Thanks
Hi Frank
3) doesn't work on my My BeagleBone Black! UART_Handle uart = UART_open(1, &uartParams); crash! Please help me to fix it. Thanks
Hi Frank
line 769
UARTIntDisable(hwAttrs->baseAddr,
UART_INT_RHR_CTI | UART_INT_THR | UART_INT_LINE_STAT); crash! Thanks
Anping,
Yes, I see an ARM exception occurs on the following CSL code which is called in UARTIntDisable():
static inline uint32_t HW_RD_REG32_RAW(uint32_t addr)
{
uint32_t regVal = *(volatile uint32_t *) ((uintptr_t) addr);
/* Donot call any functions after this. If required implement as macros */
HW_SYNC_BARRIER();
return (regVal);
}
In this case, addr=0x4802200c (base address of UART registers is 0x48022000). This strikes me as a problem with the MMU settings. I tried changing the MMU settings in your app.cfg as follows:
/* Define the base address of the 1 Meg page the peripheral resides in. */
//var peripheralBaseAddr = 0x49000000;
var peripheralBaseAddr = 0x48022000;
Unfortunately this didn't help. I'm continuing to investigate.
Anping,
I checked CM_PER_UART1_CLKCTRL and found that UART1 is disabled in your code.
CM_PER_UART1_CLKSCTRL=0x00030000
I manually enabled UART1 over JTAG:
CM_PER_UART1_CLKSCTRL=0x00000002
Now this doesn't cause an ARM exception:
UART_Handle uart = UART_open(1, &uartParams);
The CM_PER_UART1_CLKSCTRL register can be located in Registers->CM_PER.
Hence you need to update your code to enable the UART1 clock (Board_init()) & apply the updated MMU settings I have above.
Hi Frank
I confirm what you see. CM_PER_UART1_CLKSCTRL=0x00030000. I let CM_PER_UART1_CLKSCTRL=0x00000002
UART_Handle uart = UART_open(1, &uartParams); work! How to enabled UART1 automaticly. Thanks
Anping,
As I recall I sent you some materials on this topic. Please correct me if I'm mistaken so I can locate this for you. You can either add code to the existing board library for your platform, or create a custom platform.
Probably the simplest approach is to add code to the existing board library. Then the Board_init() function will enable UART1.
When the BOARD_INIT_MODULE_CLOCK is included in the Board_init() parameters, the function Board_moduleClockInit() is called in Board_init(). Add this code to pdk_am335x_1_0_16\packages\ti\board\src\bbbAM335x\bbbAM335x.c:Board_moduleClockInit()
/* UART */
status = PRCMModuleEnable(CHIPDB_MOD_ID_UART, 0U, 0U);
status = PRCMModuleEnable(CHIPDB_MOD_ID_UART, 1U, 0U); // FL: debug Anping, enable UART1 clock
If you wanted to add UART2, add another call to PRCMModuleEnable() with the second parameter set to '2U'
Next, recompile the Board library:
gmake board_lib LIMIT_SOCS="am335x" LIMIT_BOARDS="bbbAM335x" LIMIT_CORES="a8host"
Next, relink your application in CCS.
BTW I don't think you need the parameters BOARD_INIT_DDR & BOARD_INIT_PLL for Board_init().
Regards,
Frank
Hi Frank
Thank you for your reply. I face
C:\ti\pdk_am335x_1_0_16\packages\ti\board>"C:\Program Files\CMake\bin\cmake" board_lib LIMIT_SOCS="am335x" LIMIT_BOARDS="bbbAM335x" LIMIT_CORES="a8host"
CMake Error: The source directory "C:/ti/pdk_am335x_1_0_16/packages/ti/board/LIMIT_CORES=a8host" does not exist.
Specify --help for usage, or press the help button on the CMake GUI.
How to solve it? Thanks
Hi Frank
My Window 10 computer has CMake. If I want to use gmake, do I need to install some software? Thanks
Anping,
Please see this: http://software-dl.ti.com/processor-sdk-rtos/esd/docs/06_01_00_08/rtos/index_overview.html#building-pdk-using-gmake-in-windows-environment.
Regards,
Frank